Codex as a Service: Using the New OpenAI Agents API with Microsoft Foundry

    Back to Blog
    EngineeringFeatured

    Codex as a Service: Using the New OpenAI Agents API with Microsoft Foundry

    Embed Codex as a service in your own applications: use the new OpenAI Agents API with Python and connect Microsoft Foundry through MCP.

    September 12, 202612 min read
    Marcel Haas

    Marcel Haas

    Solution Architect, CEO

    marcel.haas@cnext.ch
    20+ Jahreexperience·6×Microsoft Applied Skills·SharePoint & Microsoft Copilot
    6x Microsoft Applied Skills

    Quick Answer

    Embed Codex as a service in your own applications: use the new OpenAI Agents API with Python and connect Microsoft Foundry through MCP.

    The new OpenAI Agents API can be understood as “Codex as a Service”. It makes the agent orchestration behind Codex available to your own applications through an API. OpenAI operates that orchestration; your application supplies tasks, tools, and access to the required data. OpenAI calls the technical core a “managed Codex harness”. “Codex as a Service” is an explanation of the principle here, not an official product name. OpenAI Agents API

    For example, a user might select “Create support report” in your service portal. Your backend starts a job. The agent analyses data, writes a test script, runs it in a sandbox, and creates the report. The portal displays progress and the result. Agent execution thereby becomes part of your own product.

    The comparison concerns programmable agent execution. It does not promise complete feature parity with the Codex app or its user interface. In this article, we build a technical verification agent and connect it through MCP to a specialist in Microsoft Foundry. OpenAI runs the primary agent; Foundry provides a bounded domain answer in this architecture.

    What the new API handles

    The central resource is a session. It keeps the agent configuration, conversation history, and saved work together. A new message starts a work run or directs a run already in progress. The application can continue working in the same session later. Sessions and turns

    TermMeaning for your application
    AgentModel, instructions, and available tools.
    SessionDurable context for related tasks.
    TurnA work run within the session.
    EnvironmentAn optional environment for code, files, and local tools.
    Events and itemsLive progress and stored messages or tool calls.

    This means the application needs to implement less agent mechanics itself. It remains responsible for the business boundaries: Which tasks are allowed? What data may a tool provide? How do we recognise a useful result? OpenAI describes the technical division in its API overview.

    Our example: a technical verification report

    The first task is for the agent to analyse synthetic support data. It creates a Python script, runs it, and writes a Markdown report containing the metrics actually calculated. A follow-up task adds a comparison with an operational policy.

    We propose the following architecture:

    Application with user authentication
            |
            | Task, session ID, events
            v
    OpenAI Agents API
            |
            +--- Sandbox: run Python and create report
            |
            +--- MCP tool: ask_foundry_specialist
                        |
                        v
                 Custom MCP service
                        |
                        | Microsoft Entra ID
                        v
                 Microsoft Foundry agent
                 with approved domain knowledge

    The MCP service connection is our integration design based on the documented interfaces. OpenAI supports MCP tools, and Microsoft documents how to invoke existing Foundry agents. This gives us the bridge shown here. We do not assume native deployment of the OpenAI Agents API inside Foundry. OpenAI MCP connections, Calling Foundry agents

    1. Prepare access and Python

    In your OpenAI project, create an application API key with api.agents.read, api.agents.write, and api.responses.write. The latter is required for model inference. Keep the key in the application backend, outside the sandbox. The documented API uses the beta namespace; the SDK sets the required OpenAI-Beta: agents=v1 header automatically. Quickstart prerequisites

    Install the current OpenAI SDK in a virtual environment:

    python -m venv .venv
    .\.venv\Scripts\python.exe -m pip install --upgrade openai

    Provide OPENAI_API_KEY through your local secret manager or the backend process environment. For the introduction, the example uses gpt-6-astra, as in the official quickstart. Verify access in your OpenAI project.

    2. Start a task and follow its progress

    Save the following code as technical_agent.py:

    from openai import OpenAI
    
    TASK = """
    Create demo_tickets.csv with these synthetic data:
    ticket_id,resolution_hours
    DEMO-1,2
    DEMO-2,4
    DEMO-3,6
    
    Write analyse.py to read the CSV and calculate the ticket count
    and average resolution time. Run the script.
    Create report.md with the actual results.
    Respond in English.
    """
    
    with OpenAI() as client:
        with client.beta.agents.sessions.create(
            agent={
                "model": "gpt-6-astra",
                "instructions": (
                    "Check technical tasks using executable code. "
                    "Report only results you have actually verified."
                ),
            },
            environment={"type": "openai_hosted"},
            input=TASK,
            stream=True,
        ) as events:
            for event in events:
                print(event.to_json(indent=None), flush=True)

    Start the example:

    .\.venv\Scripts\python.exe technical_agent.py

    The call creates a session and starts the job. OpenAI provides the sandbox. The console shows the event stream; store the session_id it contains in your application's job record. Agents API quickstart

    The technical result is unambiguous: three tickets and an average resolution time of four hours. Compare the report with the actual script output. A convincing-sounding answer alone is not enough for this test.

    3. Distinguish completion from failure

    In a user interface, events should update the work status. A server-sent events stream is a transport for progress, not evidence that a job succeeded.

    EventApplication response
    agent.session.turn.completedCheck and display the primary agent's result.
    agent.session.turn.failedRecord the error and mark the job as failed.
    agent.session.turn.cancelledMake the cancellation visible.
    agent.session.requires_actionCheck the pending action, such as a function call.
    agent.session.idleWait for more work; do not infer success from it.

    When subagents are enabled, distinguish their turn events from completion of the primary agent through event.turn.subagent_id. After an interrupted connection, read the session and its stored items again. The stream does not replay missed events. Events and recovery

    This matters operationally: if your application starts a new session after every connection failure, it may run the same task more than once. Store the session ID early and restore the existing state first.

    4. Continue working in the same session

    A follow-up task can extend the existing report. Send an input event to the same session:

    from openai import OpenAI
    
    
    def send_follow_up(client: OpenAI, session_id: str, text: str) -> None:
        client.beta.agents.sessions.events.create(
            session_id,
            events=[{
                "type": "agent.session.input.message",
                "input": [{
                    "role": "user",
                    "content": [{"type": "input_text", "text": text}],
                }],
            }],
        )

    In the calling code, first subscribe to client.beta.agents.sessions.events.stream(session_id). Then call the function, for example with: “Add the median and maximum resolution time to report.md. Run the script again.” This also lets you receive early events from the follow-up task. The expected additional metrics are four and six hours. Continue a session

    5. Connect Microsoft Foundry as a specialist

    The verification agent should now take an internal support policy into account. An existing Foundry agent can handle this domain task. Our MCP service exposes exactly one tool for it, ask_foundry_specialist.

    The following foundry_bridge.py file shows the local core of the service. It assumes an already configured Foundry agent that cites its sources and uses read-only tools:

    import os
    
    from azure.identity import DefaultAzureCredential, get_bearer_token_provider
    from mcp.server.fastmcp import FastMCP
    from openai import OpenAI
    
    server = FastMCP(
        "foundry-specialist",
        host="127.0.0.1",
        port=8765,
        stateless_http=True,
    )
    
    foundry = OpenAI(
        base_url=(
            os.environ["FOUNDRY_PROJECT_ENDPOINT"].rstrip("/") + "/openai/v1"
        ),
        api_key=get_bearer_token_provider(
            DefaultAzureCredential(),
            "https://ai.azure.com/.default",
        ),
        timeout=60.0,
    )
    
    
    @server.tool()
    def ask_foundry_specialist(question: str) -> str:
        """Ask the configured Foundry specialist for domain information."""
        response = foundry.responses.create(
            input=question,
            extra_body={
                "agent_reference": {
                    "type": "agent_reference",
                    "name": os.environ["FOUNDRY_AGENT_NAME"],
                }
            },
        )
        if response.status != "completed" or not response.output_text:
            raise RuntimeError("The Foundry specialist did not provide a complete answer.")
        return response.output_text
    
    
    if __name__ == "__main__":
        server.run(transport="streamable-http")

    Install openai, azure-identity, and mcp for this service. Configure FOUNDRY_PROJECT_ENDPOINT and FOUNDRY_AGENT_NAME. The service identity needs access to the Foundry project. Microsoft documents the Entra client pattern and the agent reference; the MCP wrapper is the addition required for our architecture. Entra client configuration, Foundry agent reference

    The local service deliberately binds only to loopback. For a connection from OpenAI, put it behind an authenticated HTTPS endpoint. It must forward MCP requests to the service and restrict access to the relevant users or tenants. A local address such as 127.0.0.1 is not reachable from OpenAI.

    After this deployment, add the tools field to the agent configuration in the first example. Import os there as well:

    "tools": [{
        "type": "mcp",
        "server_label": "foundry_specialist",
        "transport": {
            "type": "http",
            "server_url": os.environ["FOUNDRY_BRIDGE_MCP_URL"],
            "authorization": "Bearer " + os.environ["FOUNDRY_BRIDGE_TOKEN"],
        },
        "connection_origin": "service",
        "required": True,
    }],

    This fragment belongs in the agent dictionary. FOUNDRY_BRIDGE_TOKEN authenticates with your own MCP endpoint; it is not an OpenAI API key. The service in turn uses Entra ID for Foundry. With required: True, the turn fails if the MCP connection cannot be initialised. MCP connections and authentication

    Extend the task with: “Ask the Foundry specialist for the approved support policy. Compare the metrics with it and include its sources. If no reliable policy is available, mark the comparison as open.”

    The Agents API now handles the multi-step work and report creation. Foundry supplies a bounded domain answer. In the integration test, check both sides: did the MCP call take place, and does the report contain the correct policy with a traceable source?

    When the tools must remain in a private Azure network

    The Agents API also supports custom execution environments. There, codex exec-server runs and connects outbound to OpenAI. MCP connections can be established from this environment with connection_origin: "environment". This can reach a private MCP service if the environment has the required network access. Custom sandboxes, MCP connection paths

    You could operate such an environment as an Azure container. That is an architectural choice, not a native Foundry integration demonstrated here. OpenAI still runs the agent orchestration. A self-hosted executor therefore does not mean that the entire workflow or all processed content remains inside your Azure tenant.

    What belongs before production use

    The most important business boundary is the tool. Our example uses a service identity. It does not automatically inherit the permissions of the person who submitted the job. For tenant-specific data, the MCP service must verify the authenticated request and limit the permitted data.

    Also decide which Foundry results may be sent to OpenAI. A source citation does not replace that decision. For an initial pilot, approved technical policies and synthetic operational data are suitable.

    A robust operating model includes a job ID associated with a session ID, error handling for interrupted streams, and a retention rule for results. Back up required files before deleting a session. Session management in the quickstart

    Plan for the costs on both sides of the architecture. OpenAI charges for model usage, tools used, and hosted sandboxes where applicable, according to its respective pricing. Foundry calls and your own MCP service add costs in this design. Measure the cost per completed verification job. OpenAI billing model

    The new Agents API is particularly interesting for tasks that require several steps and verifiable work products. Our example can be expanded incrementally: first a reproducible verification report, then a clearly bounded domain answer from Foundry, and finally integration into an existing business process.

    CNEXT can help you select a suitable use case and implement the connection to your Microsoft environment. Contact CNEXT

    Agentic AI
    Teilen:

    This article was created with the support of AI and reviewed by our team. We use AI tools to produce high-quality content efficiently — the editorial responsibility always lies with our experts.

    Marcel Haas

    Marcel Haas

    Solution Architect, CEO

    6x Microsoft Applied Skills

    Deploy controlled AI agents

    We help you design harnesses, skills, tool boundaries, and evaluations for dependable AI applications.