feat(codex): experimental Codex agent mode via the Agent Client Protocol#380
Draft
pjdoland wants to merge 1 commit into
Draft
feat(codex): experimental Codex agent mode via the Agent Client Protocol#380pjdoland wants to merge 1 commit into
pjdoland wants to merge 1 commit into
Conversation
…col (plmbr#378) Add an opt-in Codex (OpenAI) agent mode that drives the chat panel over the Agent Client Protocol (ACP), the way Claude mode drives it today: streaming replies, tool-call cards with diffs, and per-tool approval. An NBI MCP tool is invoked end to end to prove the path. - ACP client backend (acp_agent.py) on a persistent worker thread, mapping ACP events onto NBI's chat surfaces, with single-flight turns and a hardened subprocess lifecycle. A small stdio MCP server (acp_mcp_server.py) exposes an NBI tool to the agent. - codex_settings + a codex_mode admin policy that defaults to force-off, plus OPENAI_API_KEY / OPENAI_BASE_URL / NBI_CODEX_CHAT_MODEL overrides, following the existing seven-place policy and settings-override conventions. - Frontend: a Codex settings tab (enable, model, key, base URL) mirroring the Claude tab, and chat-panel awareness so the input and routing follow Codex. - An in-chat agent picker (shown when more than one agent mode is enabled) that resolves a single active agent from the enabled modes and a persisted preference; with no preference the historical Claude-wins default holds. The picker is a custom icon dropdown, and the agent footer is unified (Ask/Agent and tools stay on the native model path; agent modes show only their badge). - Consistent branding: the OpenAI mark for the Codex participant and tab. - Admin gating parity with Claude: a codex_full_access policy (default force-off) pins Codex to approval_policy=untrusted so it asks before risky actions, clamped server-side; user-choice exposes a "Full access" toggle that flips the launch to approval_policy=never. README and admin-guide document the controls, the CODEX_HOME isolation, and the residual precedence caveat. Unit tests cover the ACP-to-NBI mapping, approval, the policy clamps, the active-agent resolution, the approval-arg mapping, and the credential scrub. The live path was verified in a running JupyterLab.
6c12439 to
f842fdf
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This adds an opt-in, experimental Codex (OpenAI) agent mode that drives the chat panel over the Agent Client Protocol (ACP), the way Claude mode drives it today. It is off by default and gated behind an admin policy that defaults to force-off, so it has no effect unless explicitly enabled.
The goal of this first pass is to prove that an external coding agent can run the chat loop end to end (streaming replies, tool-call cards with diffs, per-tool approval) and invoke an NBI MCP tool, using ACP as the integration layer.
What's included
acp_agent.py): a persistent worker thread that launches the Codex ACP agent and maps ACP events onto NBI's existing chat surfaces (markdown, tool-call cards, diffs, approvals). Turns are single-flight and the subprocess lifecycle is hardened. A small stdio MCP server (acp_mcp_server.py) exposes an NBI tool to the agent so the end-to-end tool path is exercised.codex_settingsblock and acodex_modeadmin policy that defaults to force-off, plusOPENAI_API_KEY/OPENAI_BASE_URL/NBI_CODEX_CHAT_MODELoverrides, following the existing policy and settings-override conventions.codex_full_accesspolicy (default force-off) pins Codex toapproval_policy=untrustedso it asks before anything beyond trusted read-only commands, clamped server-side on read and write.user-choiceexposes a "Full access" toggle that flips the launch toapproval_policy=never. Documented in the README admin table and a new admin-guide section.Testing
codex_mode/codex_full_accesspolicy clamps, the active-agent resolution, the approval-arg mapping, and the credential scrub.untrusted; user-choice flips the launch flag tonever).Design questions I'd love feedback on
Risks / follow-ups
-c approval_policycommand-line override. In the API-key path NBI also isolatesCODEX_HOME, so the config base is NBI-controlled; in the ChatGPT-auth path codex uses the user's own~/.codex. The pin relies on codex honoring the-coverride above any config it loads. A possible defense-in-depth follow-up is to also pinsandbox_mode(pending confirming codex honors it as a top-level override). On shared deployments, prefer API-key auth and keepNBI_CODEX_MODE_POLICY=force-offunless needed.Related
Relates to #378.