Last reviewed: 2026-08-30

Direct answer

Connect Microsoft Agent Framework to CometAPI with the framework’s Python OpenAIChatCompletionClient. Give that client three runtime values: a CometAPI API key read from the environment, the CometAPI base URL, and a current text-capable model ID. Pass the client to Agent, then await agent.run() with a small prompt.

This client choice is deliberate. The Microsoft Agent Framework OpenAI provider guide recommends the Responses client for new work in general, but identifies Chat Completions as the option for broad model compatibility and existing Chat Completions integrations. The CometAPI OpenAI-compatible quickstart documents the matching Chat Completions route and request shape. This tutorial joins those two documented contracts; it does not assume that every feature from either platform transfers automatically.

Start in an isolated Python environment and install the provider package:

python -m pip install agent-framework-openai

Set COMETAPI_KEY, COMETAPI_BASE_URL, and COMETAPI_MODEL in the process environment. Use the base URL shown in the CometAPI OpenAI-compatible quickstart . Keep the key outside the repository; if a diagnostic ever displays its value, render it only as [REDACTED]. The model value must be a current CometAPI model ID that supports text or chat requests.

The following minimal program exercises both the happy path and a sanitized error path. It does not log the key, prompt text, response text, headers, or full exception message.

import asyncio
import logging
import os
import sys
import time

from agent_framework import Agent
from agent_framework.openai import OpenAIChatCompletionClient

logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
logger = logging.getLogger("cometapi_agent")

required = ("COMETAPI_KEY", "COMETAPI_BASE_URL", "COMETAPI_MODEL")
missing = [name for name in required if not os.getenv(name)]
if missing:
    raise SystemExit("Missing required configuration: " + ", ".join(missing))

client = OpenAIChatCompletionClient(
    base_url=os.environ["COMETAPI_BASE_URL"],
    api_key=os.environ["COMETAPI_KEY"],
    model=os.environ["COMETAPI_MODEL"],
)

agent = Agent(
    client=client,
    name="cometapi_agent",
    instructions="Answer in one concise sentence.",
)


async def main() -> int:
    prompt = "Why should an API health check use a small prompt?"
    started = time.monotonic()

    try:
        result = await agent.run(prompt)
        elapsed_ms = round((time.monotonic() - started) * 1000)

        if not str(result).strip():
            raise RuntimeError("The agent returned no printable response.")

        logger.info(
            "agent_call_succeeded %s",
            {
                "endpoint_family": "chat_completions",
                "model": os.environ["COMETAPI_MODEL"],
                "elapsed_ms": elapsed_ms,
                "prompt_chars": len(prompt),
                "outcome": "success",
            },
        )
        print(result)
        return 0
    except Exception as exc:
        elapsed_ms = round((time.monotonic() - started) * 1000)
        logger.error(
            "agent_call_failed %s",
            {
                "endpoint_family": "chat_completions",
                "model": os.environ["COMETAPI_MODEL"],
                "elapsed_ms": elapsed_ms,
                "prompt_chars": len(prompt),
                "outcome": "error",
                "status_code": getattr(exc, "status_code", None),
                "request_id": getattr(exc, "request_id", None),
                "exception_type": type(exc).__name__,
            },
        )
        return 1


sys.exit(asyncio.run(main()))

Who this is for

This setup is for Python developers who want Microsoft Agent Framework orchestration while sending a simple, stateless Chat Completions request through CometAPI. It suits a first connectivity check, a small assistant, or a controlled migration from another OpenAI-compatible Chat Completions client.

It is not a blanket recipe for every Agent Framework feature. If your application needs the Responses API, server-managed conversation state, or hosted tools, first compare the CometAPI endpoint families . The client, endpoint, model, and desired feature must agree.

The CometAPI quickstart lists Python 3.10 or newer for its Python path. You should also be comfortable with environment variables, asynchronous Python, and reading an HTTP-style status code without printing sensitive request data.

Key takeaways

  • Use OpenAIChatCompletionClient, not the Responses-oriented client, for this Chat Completions recipe.
  • Pass a base URL, model ID, and environment-backed API key explicitly so routing is reviewable.
  • Start with one short prompt and no tools, streaming, structured output, or optional generation parameters.
  • Treat a nonempty agent result and a sanitized success log as the initial happy-path evidence.
  • Log classification fields, not keys, headers, prompts, outputs, or raw exception bodies.
  • Verify model capability before adding function tools or other optional behavior.

Sources checked

These sources independently cover the gateway contract, the framework’s custom-endpoint seam, the correct Python client family, and the package location. The implementation above stays within their overlap.

Contract details to verify

1. Verify the endpoint family before writing agent code. CometAPI’s quickstart describes an OpenAI-compatible POST /v1/chat/completions request. Microsoft documents OpenAIChatCompletionClient as the matching Agent Framework client. Supply the API base as base_url; do not pass a full Chat Completions route as the base, and do not silently switch to the Responses client while keeping Chat Completions assumptions.

2. Verify configuration without exposing it. Confirm that all three environment-variable names exist in the same process that launches Python. Check only presence and expected non-secret identifiers. A safe configuration summary may show the model, endpoint family, and whether each required variable is present. It must never show the key’s value. Follow the same repository boundary described in Keep CometAPI Keys Out of Tutorial Repositories .

3. Verify the model separately from the framework. A syntactically valid model string is not proof that the model exists or supports the requested operation. Select a current text-capable CometAPI model ID. For a first run, omit tools, streaming, JSON response formats, temperature, and token-budget options. Each optional parameter creates another possible incompatibility and makes a routing error harder to isolate.

4. Run a concrete happy-path workflow. Use a short, deterministic instruction and one short user prompt. Launch the program once. A passing first run has four observable properties: the process reaches agent.run(), it returns a printable nonempty result, the success log records endpoint_family, model, elapsed_ms, prompt_chars, and outcome, and the process exits without entering the exception branch. Save the sanitized event in your normal log system; do not save the generated content merely to prove connectivity.

5. Run a controlled error-path workflow. In a non-production environment, replace the model setting with an intentionally nonexistent, non-secret identifier and run the same small prompt. The error branch should capture an exception type and, when the client exposes them, a status code and request ID. It should not print request headers, environment contents, prompt text, response bodies, or the exception’s full string. It should exit with a nonzero status without re-raising the client exception. Restore the valid model immediately after the test. This verifies observability without manufacturing or disclosing a credential.

6. Classify before retrying. Configuration and authentication failures need correction, not automatic retries. A missing model needs a catalog or capability check. Rate or transient service failures may enter a bounded retry policy, but only after the application distinguishes them from permanent request errors. Keep retry examples inside the documented boundary by using the CometAPI retry example notes rather than treating every exception as retryable.

7. Keep logs intentionally small. The recommended sanitized fields are event, endpoint_family, model, elapsed_ms, prompt_chars, outcome, status_code, request_id, and exception_type. Depending on your environment, even prompts and outputs can contain customer or business data, so they are deliberately absent. Avoid dumping client objects: their representations can change and may include configuration you did not intend to record.

Failure modes

The request is rejected as unauthenticated. First confirm the key variable is present in the Python process, not merely in a different shell, terminal tab, or deployment stage. Confirm that the client receives the CometAPI key through api_key. Do not log the value while debugging. Treat an authentication rejection as permanent until configuration is corrected.

The SDK calls the wrong host. This usually means base_url was omitted, loaded from the wrong environment, or replaced by a default. Record the endpoint family and a non-secret configuration-presence check, then compare the runtime value with the CometAPI quickstart. Do not append the full request route to a value that the client expects to be only the API base.

The model is not found or cannot serve chat. Model catalogs change, and not every model supports every modality or feature. Recheck the current CometAPI model ID and confirm it is suitable for text or chat. Do not respond by cycling through undocumented aliases in production.

The wrong Agent Framework client is selected. OpenAIChatClient targets the Responses API, while this recipe deliberately uses OpenAIChatCompletionClient. The names are similar, but the protocol contracts are not interchangeable. Revisit the Microsoft provider guide and choose based on the endpoint actually being called.

A minimal call works but tools or structured output fail. That result isolates the problem to an added capability rather than basic routing. Confirm that the selected model and endpoint support the added feature, add only one capability at a time, and inspect the payload boundary with Review Tool-Call Payloads in CometAPI Examples .

The service returns a rate or transient failure. Preserve the safe status, request ID, elapsed time, and exception type. Apply only a bounded retry policy appropriate to that class of failure. Never retry a malformed request or invalid model indefinitely, and never include the key or raw response body in retry logs.

The result is empty or unexpectedly shaped. Keep the raw result out of shared logs. Reproduce with the one-sentence prompt, remove optional parameters, and compare a direct contract check with the CometAPI Chat Completions smoke test . This separates gateway behavior from Agent Framework rendering or state.

FAQ

Why use Chat Completions if Microsoft recommends Responses for new work?

Microsoft’s recommendation is general. It also says Chat Completions is appropriate for broad compatibility and existing Chat Completions integrations. This article specifically targets CometAPI’s documented OpenAI-compatible Chat Completions path. Choose the Responses client only when you have verified the corresponding endpoint and feature contract for your application.

Can I hardcode the CometAPI key for a quick test?

No. Keep it in the runtime environment or your deployment’s secret-management boundary. Source files, notebooks, copied terminal transcripts, exception dumps, and screenshots are all poor places for credential values. Use [REDACTED] whenever a human-readable diagnostic needs a placeholder.

Should the tutorial pin the package version?

Check the current registry metadata and your compatibility constraints at implementation time. A stale version copied from an article can hide important dependency changes. Validate in an isolated environment, record the version in your application’s dependency lock, and upgrade through your normal test process.

What proves the integration works?

For the initial contract, require a nonempty result from one small prompt, a clean process exit, and a sanitized success event with the expected model and endpoint family. Then demonstrate that a controlled bad model reaches the safe error branch, emits no client-exception traceback, and exits nonzero. Those checks prove basic routing and observability; they do not prove every model feature.

Can I add a function tool next?

Agent Framework documents function tools for its Chat Completions client, but the selected model and gateway path must also support the required tool-call behavior. Establish the plain-text baseline first, confirm the current model capability, and then add one typed local function with a narrow schema.

What should I send to support when a request fails?

Share non-secret evidence: approximate time, endpoint family, model ID, sanitized status code, request ID when available, exception type, and whether the same minimal prompt fails consistently. Do not send keys, headers, full environment dumps, or customer prompts.

Reader next step

Create an isolated environment, configure the three runtime values, and run the minimal program unchanged. Confirm the happy path, then exercise the controlled bad-model path and inspect only the sanitized fields. Verify that the error run exits nonzero without displaying the client exception text. Once that baseline is stable, add one feature at a time and repeat the same checks.

If you need CometAPI access for this integration, Start with CometAPI .