Skip to content

Python: Add OpenAI Codex SDK integration (agent-framework-codex)#4375

Open
LEDazzio01 wants to merge 8 commits intomicrosoft:mainfrom
LEDazzio01:feature/add-codex-sdk-integration
Open

Python: Add OpenAI Codex SDK integration (agent-framework-codex)#4375
LEDazzio01 wants to merge 8 commits intomicrosoft:mainfrom
LEDazzio01:feature/add-codex-sdk-integration

Conversation

@LEDazzio01
Copy link
Contributor

Motivation and Context

Closes #4370

The Microsoft Agent Framework currently supports managed agent SDK integrations for Claude (agent-framework-claude) and GitHub Copilot (agent-framework-github-copilot), but not for OpenAI Codex. This PR adds agent-framework-codex to provide parity across the three major agentic coding SDKs.

Description

Adds a new Python package agent-framework-codex that wraps the codex-sdk as a managed agent, following the same conventions as the existing Claude and GitHub Copilot packages.

New Files

File Description
python/packages/codex/pyproject.toml Package configuration (flit-core, ruff, pyright, mypy, pytest)
python/packages/codex/README.md Package README with install instructions
python/packages/codex/LICENSE MIT License
python/packages/codex/AGENTS.md Package metadata for agent discovery
python/packages/codex/agent_framework_codex/__init__.py Public API: CodexAgent, CodexAgentOptions, CodexAgentSettings
python/packages/codex/agent_framework_codex/_agent.py Core implementation wrapping CodexSDKClient
python/packages/codex/tests/test_codex_agent.py Comprehensive unit tests (all mocked, no external deps)

Key Classes

  • CodexAgentSettings — TypedDict for env-based config (CODEX_AGENT_ prefix)
  • CodexAgentOptions — TypedDict for per-request options (model, system_prompt, etc.)
  • CodexAgentBaseAgent subclass with full support for:
    • Streaming and non-streaming responses
    • Session management (service_session_id)
    • Tool conversion (FunctionTool → SDK MCP tools)
    • Async context manager (async with CodexAgent() as agent)
    • Structured output propagation
    • Runtime option changes (model, permission_mode)

Usage

from agent_framework_codex import CodexAgent

async with CodexAgent(
    instructions="You are a helpful coding assistant.",
    default_options={"model": "codex-mini-latest"},
) as agent:
    response = await agent.run("Write a Python function that reverses a linked list.")
    print(response.text)

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR title follows the repo convention
  • Tests added to cover the change
  • All new and existing tests pass

Copilot AI review requested due to automatic review settings March 1, 2026 19:38
@markwallace-microsoft markwallace-microsoft added documentation Improvements or additions to documentation python labels Mar 1, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Python managed-agent integration package, agent-framework-codex, that wraps the Codex SDK to provide an Agent Framework BaseAgent implementation with streaming, sessions, tool bridging (via MCP), and structured-output propagation.

Changes:

  • Introduces CodexAgent, CodexAgentOptions, and CodexAgentSettings plus supporting implementation to run Codex via CodexSDKClient with streaming updates and session resume support.
  • Adds a full unit-test suite for initialization, streaming/non-streaming runs, sessions, tool conversion, runtime options, and structured output.
  • Adds package scaffolding (pyproject.toml, README, LICENSE, AGENTS.md).

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
python/packages/codex/agent_framework_codex/_agent.py Implements the Codex managed agent (client lifecycle, sessions, tool→MCP conversion, streaming).
python/packages/codex/tests/test_codex_agent.py Adds mocked unit tests covering key agent behaviors.
python/packages/codex/pyproject.toml Defines the new package metadata, dependencies, and tooling config.
python/packages/codex/agent_framework_codex/init.py Exposes the package public API + version.
python/packages/codex/README.md Minimal install/get-started documentation.
python/packages/codex/LICENSE Adds MIT license text for the package.
python/packages/codex/AGENTS.md Agent discovery metadata for the new package.

session_id: The session ID to use, or None for a new session.
"""
needs_new_client = (
not self._started or self._client is None or (session_id and session_id != self._current_session_id)
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_ensure_session() only recreates the client when (session_id and session_id != self._current_session_id). If the agent previously resumed a session (self._current_session_id is set) and a caller later runs with a fresh AgentSession (service_session_id is None), this condition evaluates false and the existing client/session will be reused, so the "new" session is not actually isolated. Consider treating None as a valid session change (e.g., recreate whenever session_id != self._current_session_id) and add a test that runs once with a resumed session_id then again with a new session (None) to ensure a new session is started.

Suggested change
not self._started or self._client is None or (session_id and session_id != self._current_session_id)
not self._started
or self._client is None
or session_id != self._current_session_id

Copilot uses AI. Check for mistakes.

- **`CodexAgent`** - Agent using Codex's native agent capabilities
- **`CodexAgentOptions`** - Options for Codex agent configuration
- **`CodexAgentSettings`** - Pydantic settings for configuration
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AGENTS.md says CodexAgentSettings are "Pydantic settings", but this package uses the framework’s load_settings() helper which populates a TypedDict (and the settings loader explicitly notes it replaces the previous pydantic-settings approach). Update this description to avoid misleading consumers about configuration behavior and dependencies.

Suggested change
- **`CodexAgentSettings`** - Pydantic settings for configuration
- **`CodexAgentSettings`** - TypedDict-based settings populated via the framework's `load_settings()` helper

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

@LEDazzio01 LEDazzio01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the thorough review! All 3 comments addressed in the latest commits:

  1. _ensure_session session isolation (_agent.py) — Fixed. Removed the extra session_id and guard so None is now treated as a distinct session identity. Added a dedicated regression test (test_ensure_session_recreates_when_resumed_then_fresh) that verifies switching from a resumed session back to None correctly creates a new client. (commit 8df3a83, 3b95a7d)

  2. pyproject.toml dependency — Aligned agent-framework-core>=1.0.0rc2>=1.0.0rc1 to match the other managed-agent integrations. (commit 850cb45)

  3. AGENTS.md description — Updated "Pydantic settings" → "TypedDict-based settings populated via the framework's load_settings() helper". (commit ebdcb5e)

"Typing :: Typed",
]
dependencies = [
"agent-framework-core>=1.0.0rc1",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sure you rebase to the latest and then update this to rc2

response = await agent.run("Greet Alice")
"""

AGENT_PROVIDER_NAME: ClassVar[str] = "openai.codex"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this a value defined in the Otel genAI spec? or should we just have openai in here?

)


class CodexAgent(BaseAgent, Generic[OptionsT]):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have a PR open to add Telemetry to the ClaudeAgent, splitting it into a RawClaudeAgent and then ClaudeAgent is built from RawClaudeAgent and AgentTelemetryLayer, let's do the same here.

*,
stream: bool = False,
session: AgentSession | None = None,
options: OptionsT | MutableMapping[str, Any] | None = None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the MutableMapping needed here? I think it should be able to just be OptionsT

**kwargs: Any,
) -> AgentResponse[Any]: ...

def run(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it make sense to also support background: bool = False here? check OpenAIResponses and A2A for how that works now.

LEDazzio01 and others added 8 commits March 2, 2026 16:18
Adds LICENSE, README.md, AGENTS.md, and pyproject.toml for the new
agent-framework-codex package. Closes microsoft#4370.
Core implementation of the agent-framework-codex package with:
- CodexAgentSettings for env-based configuration
- CodexAgentOptions for per-request options
- CodexAgent wrapping CodexSDKClient with streaming, tools, sessions
Tests cover settings, initialization, lifecycle, run (streaming and
non-streaming), session management, tool conversion, permissions,
error handling, format prompt, options preparation, and structured output.
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Previously, _ensure_session() only recreated the client when
(session_id and session_id != self._current_session_id), which
meant switching from a resumed session back to a fresh session
(None) would incorrectly reuse the existing client. Now we compare
session_id != self._current_session_id directly, so None is treated
as a valid, distinct session identity.

Co-authored-by: Copilot <copilot@github.com>
Verifies that _ensure_session creates a new client when switching
from a resumed session (non-None) back to a fresh session (None).

Co-authored-by: Copilot <copilot@github.com>
- Rebase onto latest main
- Bump agent-framework-core dependency to >=1.0.0rc2
- Split CodexAgent into RawCodexAgent + CodexAgent(AgentTelemetryLayer)
  following A2AAgent pattern as requested
- Remove MutableMapping from run() options parameter type
- Export RawCodexAgent from __init__.py
@LEDazzio01 LEDazzio01 force-pushed the feature/add-codex-sdk-integration branch from 3b95a7d to b752405 Compare March 2, 2026 21:21
@LEDazzio01
Copy link
Contributor Author

Thanks for the thorough review @eavanvalkenburg! I've addressed all feedback in the latest force-push (rebased onto latest main):

✅ Changes made:

  1. Rebased + bumped dependencyagent-framework-core>=1.0.0rc2

  2. AGENT_PROVIDER_NAME — kept as "openai.codex", following the {provider}.{product} convention used by ClaudeAgent ("anthropic.claude"). Happy to change to just "openai" if there's a specific OTel GenAI spec value you'd prefer.

  3. Telemetry layer split — implemented! Now:

    • RawCodexAgent(BaseAgent) — core implementation without telemetry
    • CodexAgent(AgentTelemetryLayer, RawCodexAgent) — with OTel instrumentation
    • Both exported from __init__.py
    • Follows the A2AAgent(AgentTelemetryLayer, BaseAgent) pattern
  4. Removed MutableMapping from run() options parameter → simplified to OptionsT | None

  5. background: bool — the Codex SDK's session model (CLI subprocess) doesn't have a direct equivalent to A2A's background task polling. The SDK doesn't expose task IDs or resubscription like the A2A protocol. I'd suggest deferring this to a follow-up once there's clearer support in the Codex SDK for detached/background execution. Let me know if you'd prefer a different approach.

Ready for another look! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.NET: Python: [Feature]: Add OpenAI Codex SDK integration (agent-framework-codex)

4 participants