Skip to content

feat(cli): add codex init templates (sync / async / temporal)#436

Merged
declan-scale merged 5 commits into
nextfrom
declan-scale/init-templates-codex
Jun 24, 2026
Merged

feat(cli): add codex init templates (sync / async / temporal)#436
declan-scale merged 5 commits into
nextfrom
declan-scale/init-templates-codex

Conversation

@declan-scale

@declan-scale declan-scale commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Final slice of #425. Adds the codex agentex init templates across all three tiers.

  • New default-codex, sync-codex, temporal-codex template dirs.
  • Wires DEFAULT_CODEX, SYNC_CODEX, TEMPORAL_CODEX into init.py (enum, project-files map, prompts). TemplateType is now complete at 19.
  • Scaffolded code imports CodexTurn from the agentex.lib.adk facade.

Test plan

Notes

Stacked on #435. Retarget to next after the chain merges.

🤖 Generated with Claude Code

Greptile Summary

  • Adds Codex scaffold templates for the default, sync, and Temporal init tiers.
  • Wires the new Codex template types into the CLI init enum, project file map, and prompts.
  • Includes generated Docker, uv, manifest, environment, README, notebook, and agent implementation files using the Codex ADK facade.

Confidence Score: 4/5

The Codex scaffold templates need fixes before merge because fresh generated projects can fail to build and async Codex task handling can fork conversation state.

Focused runtime checks reproduced the Docker template parsing issue, the uv lockfile mismatch, and the concurrent task state overwrite while the rest of the change is localized template wiring.

src/agentex/lib/cli/templates/default-codex/Dockerfile.j2, src/agentex/lib/cli/templates/default-codex/Dockerfile-uv.j2, src/agentex/lib/cli/templates/default-codex/project/acp.py.j2, plus the sibling sync and Temporal Codex templates with the same Dockerfile patterns.

T-Rex T-Rex Logs

What T-Rex did

  • Reproduced a Dockerfile RUN fragment syntax error in the default-codex rendering path and confirmed the shell parser failed on the broken line continuation.
  • Reproduced the missing generated uv.lock in the scaffold, showing that the Dockerfile COPY source validation failed due to the missing uv.lock.
  • Reproduced the concurrent turns fork state using a focused async harness, which showed the last finisher overwrote the codex_thread_id.
  • Compared before and after states for codex-init-templates rendering, confirming that initially templates were missing and later rendering succeeded with TemplateType_count showing 19.
  • Compared before/after runs for the codex scaffold Python correction, confirming six files were missing at base and six files exist after correction with successful parsing and imports.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (1)

  1. src/agentex/lib/cli/templates/default-codex/manifest.yaml.j2, line 599-613 (link)

    P1 LITELLM_API_KEY credential won't satisfy codex exec

    The active credentials entry maps LITELLM_API_KEY into the container, but codex exec reads OPENAI_API_KEY directly from the environment. When a user scaffolds this template and deploys, the Kubernetes secret for litellm-api-key is mounted but OPENAI_API_KEY is never set, so every codex exec invocation will fail with an auth error. The credential name (and the env: entry below it) should reference OPENAI_API_KEY / openai-api-key to match what the CLI actually consumes. The same issue is present in sync-codex/manifest.yaml.j2.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/agentex/lib/cli/templates/default-codex/manifest.yaml.j2
    Line: 599-613
    
    Comment:
    **`LITELLM_API_KEY` credential won't satisfy `codex exec`**
    
    The active credentials entry maps `LITELLM_API_KEY` into the container, but `codex exec` reads `OPENAI_API_KEY` directly from the environment. When a user scaffolds this template and deploys, the Kubernetes secret for `litellm-api-key` is mounted but `OPENAI_API_KEY` is never set, so every `codex exec` invocation will fail with an auth error. The credential name (and the `env:` entry below it) should reference `OPENAI_API_KEY` / `openai-api-key` to match what the CLI actually consumes. The same issue is present in `sync-codex/manifest.yaml.j2`.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code

Fix All in Claude Code

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
src/agentex/lib/cli/templates/default-codex/Dockerfile-uv.j2:34-38
**Missing generated lockfile**

The uv Dockerfile requires `uv.lock`, but `agentex init` only renders `pyproject.toml` for uv projects and does not create a lockfile. A freshly scaffolded Codex project generated with the uv option can fail its Docker build at this `COPY` or at `uv sync --locked` before the agent starts. The same lockfile assumption should be fixed in the sync and Temporal Codex uv Dockerfiles.

### Issue 2 of 2
src/agentex/lib/cli/templates/default-codex/project/acp.py.j2:159-177
**Concurrent turns fork state**

This handler reads `state.codex_thread_id`, then awaits the full Codex subprocess stream before saving the new `turn.session_id`. If two `task/event/send` calls for the same async task arrive close together, both handlers can read the same old thread id or `None`, run independent Codex turns, and then race to overwrite the stored thread id. The next user message resumes only one branch, so the Codex conversation history can lose one of the messages.

Reviews (18): Last reviewed commit: "fix(cli): wire OPENAI_API_KEY and serial..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

@declan-scale declan-scale force-pushed the declan-scale/init-templates-claude-code branch from a92d37b to ff359de Compare June 23, 2026 15:28
@declan-scale declan-scale force-pushed the declan-scale/init-templates-codex branch from 9d0ea68 to a891d35 Compare June 23, 2026 15:28
@declan-scale

Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread src/agentex/lib/cli/templates/temporal-codex/Dockerfile-uv.j2
Comment thread src/agentex/lib/cli/templates/default-codex/.env.example.j2
Comment thread src/agentex/lib/cli/templates/sync-codex/dev.ipynb.j2
@declan-scale declan-scale force-pushed the declan-scale/init-templates-claude-code branch from ff359de to e031d5d Compare June 23, 2026 15:45
@declan-scale declan-scale force-pushed the declan-scale/init-templates-codex branch from a891d35 to be6b158 Compare June 23, 2026 15:47
@declan-scale

Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread src/agentex/lib/cli/templates/default-codex/project/acp.py.j2 Outdated
Comment thread src/agentex/lib/cli/templates/sync-codex/project/acp.py.j2 Outdated
Comment thread src/agentex/lib/cli/templates/temporal-codex/project/activities.py.j2 Outdated
@declan-scale declan-scale force-pushed the declan-scale/init-templates-claude-code branch from e031d5d to 8f7854a Compare June 23, 2026 16:25
@declan-scale declan-scale force-pushed the declan-scale/init-templates-codex branch from be6b158 to 2eefec2 Compare June 23, 2026 16:25
@declan-scale

Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread src/agentex/lib/cli/templates/default-codex/Dockerfile.j2
@declan-scale declan-scale force-pushed the declan-scale/init-templates-claude-code branch from 8f7854a to 6e3f0cf Compare June 23, 2026 16:52
@declan-scale declan-scale force-pushed the declan-scale/init-templates-codex branch from 2eefec2 to 42db83c Compare June 23, 2026 16:52
@declan-scale

Copy link
Copy Markdown
Contributor Author

@greptile review

@declan-scale declan-scale force-pushed the declan-scale/init-templates-codex branch from 42db83c to 889f793 Compare June 23, 2026 17:07
@declan-scale

Copy link
Copy Markdown
Contributor Author

@greptile review

@declan-scale declan-scale force-pushed the declan-scale/init-templates-codex branch from 889f793 to ace66e2 Compare June 23, 2026 17:25
@declan-scale

Copy link
Copy Markdown
Contributor Author

@greptile review

Comment thread src/agentex/lib/cli/templates/default-codex/manifest.yaml.j2 Outdated
Comment thread src/agentex/lib/cli/templates/temporal-codex/project/workflow.py.j2 Outdated
@declan-scale

Copy link
Copy Markdown
Contributor Author

@greptile review

@declan-scale declan-scale force-pushed the declan-scale/init-templates-claude-code branch from 47ea82c to 2003757 Compare June 23, 2026 19:53
@declan-scale declan-scale force-pushed the declan-scale/init-templates-codex branch from d489113 to 412b1c6 Compare June 23, 2026 19:53
@declan-scale declan-scale force-pushed the declan-scale/init-templates-claude-code branch from 2003757 to 755d18e Compare June 23, 2026 19:57
@declan-scale declan-scale force-pushed the declan-scale/init-templates-codex branch from 412b1c6 to 3aaa35e Compare June 23, 2026 19:57
@declan-scale declan-scale force-pushed the declan-scale/init-templates-claude-code branch from 755d18e to 63904c2 Compare June 23, 2026 22:04
@declan-scale declan-scale force-pushed the declan-scale/init-templates-codex branch from 3aaa35e to 5d5a0e8 Compare June 23, 2026 22:04
@declan-scale declan-scale force-pushed the declan-scale/init-templates-claude-code branch from 63904c2 to f819115 Compare June 23, 2026 22:29
@declan-scale declan-scale force-pushed the declan-scale/init-templates-codex branch from 5d5a0e8 to b5cbe37 Compare June 23, 2026 22:29
@declan-scale declan-scale force-pushed the declan-scale/init-templates-claude-code branch 3 times, most recently from f819115 to 4f2002c Compare June 24, 2026 01:57
Base automatically changed from declan-scale/init-templates-claude-code to next June 24, 2026 02:08
declan-scale and others added 5 commits June 23, 2026 22:08
Add default-codex, sync-codex and temporal-codex templates across all three
tiers, wiring the new TemplateType entries into the init flow. Scaffolded code
imports CodexTurn from the agentex.lib.adk facade.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address Greptile review: wrap the streaming call in try/finally across the
default, sync and temporal codex templates so the codex subprocess is killed
and reaped even when auto_send_turn / yield_turn raises or the async generator
is abandoned. Previously a failed turn left codex blocked on a full stdout pipe
buffer, leaking an OS process per failure until the server/worker restarted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address Greptile review: the default, sync and temporal codex Dockerfiles
installed nodejs/npm but never the codex CLI, so scaffolded containers hit
FileNotFoundError on `codex` for every request. Add
`npm install -g @openai/codex`, matching the claude-code templates.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Round-3 Greptile parity: the uv-path Dockerfile-uv.j2 variants (default, sync,
temporal) installed node/npm but not the `codex` CLI. Mirror the
npm install -g @openai/codex step already added to the pip Dockerfiles so
use_uv=True containers are functional.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Round-5 Greptile review (parity with the claude-code fixes):
- default/sync/temporal codex manifests now map OPENAI_API_KEY (the key the
  codex CLI actually reads) instead of LITELLM_API_KEY, and no longer set an
  empty-string env value that would shadow it at runtime.
- temporal-codex workflow serializes signal turns with an asyncio.Lock so
  overlapping messages don't race on _codex_thread_id and fork the session.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@declan-scale declan-scale force-pushed the declan-scale/init-templates-codex branch from b5cbe37 to e089205 Compare June 24, 2026 02:09
Comment on lines +34 to +38
COPY {{ project_path_from_build_root }}/pyproject.toml {{ project_path_from_build_root }}/uv.lock ./

# Install dependencies (without project itself, for layer caching)
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked --no-install-project --no-dev

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Missing generated lockfile

The uv Dockerfile requires uv.lock, but agentex init only renders pyproject.toml for uv projects and does not create a lockfile. A freshly scaffolded Codex project generated with the uv option can fail its Docker build at this COPY or at uv sync --locked before the agent starts. The same lockfile assumption should be fixed in the sync and Temporal Codex uv Dockerfiles.

Artifacts

Repro: scaffold render and Dockerfile COPY validation script

  • Contains supporting evidence from the run (text/x-python; charset=utf-8).

Repro: generated scaffold listing and missing uv.lock COPY validation failure

  • Keeps the command output available without making the summary code-heavy.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agentex/lib/cli/templates/default-codex/Dockerfile-uv.j2
Line: 34-38

Comment:
**Missing generated lockfile**

The uv Dockerfile requires `uv.lock`, but `agentex init` only renders `pyproject.toml` for uv projects and does not create a lockfile. A freshly scaffolded Codex project generated with the uv option can fail its Docker build at this `COPY` or at `uv sync --locked` before the agent starts. The same lockfile assumption should be fixed in the sync and Temporal Codex uv Dockerfiles.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code

Comment on lines +159 to +177
task_state = await adk.state.get_by_task_and_agent(task_id=task_id, agent_id=agent_id)
if task_state is None:
state = ConversationState()
task_state = await adk.state.create(task_id=task_id, agent_id=agent_id, state=state)
else:
state = ConversationState.model_validate(task_state.state)

state.turn_number += 1

async with adk.tracing.span(
trace_id=task_id,
task_id=task_id,
name=f"Turn {state.turn_number}",
input={"message": user_message},
data={"__span_type__": "AGENT_WORKFLOW"},
) as turn_span:
start_ms = int(time.monotonic() * 1000)

process = await _spawn_codex(MODEL, thread_id=state.codex_thread_id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Concurrent turns fork state

This handler reads state.codex_thread_id, then awaits the full Codex subprocess stream before saving the new turn.session_id. If two task/event/send calls for the same async task arrive close together, both handlers can read the same old thread id or None, run independent Codex turns, and then race to overwrite the stored thread id. The next user message resumes only one branch, so the Codex conversation history can lose one of the messages.

Artifacts

Repro: async harness generated from the template handler with mocked Codex and state services

  • Contains supporting evidence from the run (text/x-python; charset=utf-8).

Repro: verbose harness output showing forked thread IDs, write order, final state, and assertions

  • Keeps the command output available without making the summary code-heavy.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agentex/lib/cli/templates/default-codex/project/acp.py.j2
Line: 159-177

Comment:
**Concurrent turns fork state**

This handler reads `state.codex_thread_id`, then awaits the full Codex subprocess stream before saving the new `turn.session_id`. If two `task/event/send` calls for the same async task arrive close together, both handlers can read the same old thread id or `None`, run independent Codex turns, and then race to overwrite the stored thread id. The next user message resumes only one branch, so the Codex conversation history can lose one of the messages.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

@declan-scale declan-scale merged commit 0fadfd7 into next Jun 24, 2026
48 checks passed
@declan-scale declan-scale deleted the declan-scale/init-templates-codex branch June 24, 2026 02:16
@stainless-app stainless-app Bot mentioned this pull request Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants