-
Notifications
You must be signed in to change notification settings - Fork 9
feat(cli): add codex init templates (sync / async / temporal) #436
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d3bc5a2
d542756
a1bb2ca
d7b8227
e089205
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # Python | ||
| __pycache__/ | ||
| *.py[cod] | ||
| *$py.class | ||
| *.so | ||
| .Python | ||
| build/ | ||
| develop-eggs/ | ||
| dist/ | ||
| downloads/ | ||
| eggs/ | ||
| .eggs/ | ||
| lib/ | ||
| lib64/ | ||
| parts/ | ||
| sdist/ | ||
| var/ | ||
| wheels/ | ||
| *.egg-info/ | ||
| .installed.cfg | ||
| *.egg | ||
|
|
||
| # Environments | ||
| .env** | ||
| .venv | ||
| env/ | ||
| venv/ | ||
| ENV/ | ||
| env.bak/ | ||
| venv.bak/ | ||
|
|
||
| # IDE | ||
| .idea/ | ||
| .vscode/ | ||
| *.swp | ||
| *.swo | ||
|
|
||
| # Git | ||
| .git | ||
| .gitignore | ||
|
|
||
| # Misc | ||
| .DS_Store |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| # {{ agent_name }} - Environment Variables | ||
| # Copy this file to .env and fill in the values | ||
|
|
||
| # API key used by the codex CLI (`codex exec` reads OPENAI_API_KEY directly) | ||
| OPENAI_API_KEY= | ||
|
|
||
| # LLM base URL (optional - override to use a different provider) | ||
| # OPENAI_BASE_URL= | ||
|
|
||
| # SGP Configuration (optional - for tracing) | ||
| # SGP_API_KEY= | ||
| # SGP_ACCOUNT_ID= | ||
| # SGP_CLIENT_BASE_URL= | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # syntax=docker/dockerfile:1.3 | ||
| FROM python:3.12-slim | ||
| COPY --from=ghcr.io/astral-sh/uv:0.6.4 /uv /uvx /bin/ | ||
|
|
||
| # Install system dependencies | ||
| RUN apt-get update && apt-get install -y \ | ||
| htop \ | ||
| vim \ | ||
| curl \ | ||
| tar \ | ||
| python3-dev \ | ||
| postgresql-client \ | ||
| build-essential \ | ||
| libpq-dev \ | ||
| gcc \ | ||
| cmake \ | ||
| netcat-openbsd \ | ||
| nodejs \ | ||
| npm \ | ||
| && apt-get clean \ | ||
| && rm -rf /var/lib/apt/lists/** | ||
|
|
||
| # Install the codex CLI: the agent shells out to `codex` on every turn, so the | ||
| # binary must be present in the runtime image. | ||
| RUN npm install -g @openai/codex | ||
|
|
||
| ENV UV_COMPILE_BYTECODE=1 | ||
| ENV UV_LINK_MODE=copy | ||
| ENV UV_HTTP_TIMEOUT=1000 | ||
|
|
||
| WORKDIR /app/{{ project_path_from_build_root }} | ||
|
|
||
| # Copy dependency files for layer caching | ||
| 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 | ||
|
Comment on lines
+34
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The uv Dockerfile requires ArtifactsRepro: scaffold render and Dockerfile COPY validation script
Repro: generated scaffold listing and missing uv.lock COPY validation failure
Prompt To Fix With AIThis 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! |
||
|
|
||
| # Copy the project code | ||
| COPY {{ project_path_from_build_root }}/project ./project | ||
|
|
||
| # Install the project | ||
| RUN --mount=type=cache,target=/root/.cache/uv \ | ||
| uv sync --locked --no-dev | ||
|
|
||
| ENV PATH="/app/{{ project_path_from_build_root }}/.venv/bin:$PATH" | ||
| ENV PYTHONPATH=/app | ||
|
|
||
| # Run the agent using uvicorn | ||
| CMD ["uvicorn", "project.acp:acp", "--host", "0.0.0.0", "--port", "8000"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| # syntax=docker/dockerfile:1.3 | ||
| FROM python:3.12-slim | ||
| COPY --from=ghcr.io/astral-sh/uv:0.6.4 /uv /uvx /bin/ | ||
|
|
||
| # Install system dependencies | ||
| RUN apt-get update && apt-get install -y \ | ||
| htop \ | ||
| vim \ | ||
| curl \ | ||
| tar \ | ||
| python3-dev \ | ||
| postgresql-client \ | ||
| build-essential \ | ||
| libpq-dev \ | ||
| gcc \ | ||
| cmake \ | ||
| netcat-openbsd \ | ||
| nodejs \ | ||
| npm \ | ||
| && apt-get clean \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
greptile-apps[bot] marked this conversation as resolved.
|
||
|
|
||
| # Install the codex CLI: the agent shells out to `codex` on every turn, so the | ||
| # binary must be present in the runtime image. | ||
| RUN npm install -g @openai/codex | ||
|
|
||
| RUN uv pip install --system --upgrade pip setuptools wheel | ||
|
|
||
| ENV UV_HTTP_TIMEOUT=1000 | ||
|
|
||
| # Copy just the requirements file to optimize caching | ||
| COPY {{ project_path_from_build_root }}/requirements.txt /app/{{ project_path_from_build_root }}/requirements.txt | ||
|
|
||
| WORKDIR /app/{{ project_path_from_build_root }} | ||
|
|
||
| # Install the required Python packages | ||
| RUN uv pip install --system -r requirements.txt | ||
|
|
||
| # Copy the project code | ||
| COPY {{ project_path_from_build_root }}/project /app/{{ project_path_from_build_root }}/project | ||
|
|
||
| # Set environment variables | ||
| ENV PYTHONPATH=/app | ||
|
|
||
| # Run the agent using uvicorn | ||
| CMD ["uvicorn", "project.acp:acp", "--host", "0.0.0.0", "--port", "8000"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # {{ agent_name }} - AgentEx Async Codex Agent | ||
|
|
||
| This template builds an **asynchronous** (non-Temporal) agent that drives the | ||
| **Codex CLI** through the unified harness surface on AgentEx: | ||
| - Spawns `codex exec --json` as a local subprocess | ||
| - Wraps the CLI's stdout stream in a `CodexTurn` | ||
| - Delivers canonical `StreamTaskMessage*` events via `UnifiedEmitter.auto_send_turn` | ||
| (the async Redis push path), so the UI receives output in real time | ||
| - Persists the codex session/thread ID via `adk.state` for multi-turn memory | ||
| - Tracing integration to SGP / AgentEx | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - The `codex` CLI installed and on your `PATH` (`npm install -g @openai/codex`) | ||
| - An `OPENAI_API_KEY` in your environment | ||
|
|
||
| ## Running the Agent | ||
|
|
||
| ```bash | ||
| agentex agents run --manifest manifest.yaml | ||
| ``` | ||
|
|
||
| ## Project Structure | ||
|
|
||
| ``` | ||
| {{ project_name }}/ | ||
| βββ project/ | ||
| β βββ __init__.py | ||
| β βββ acp.py # ACP server, subprocess spawn, state, and event handlers | ||
| βββ Dockerfile | ||
| βββ manifest.yaml | ||
| βββ dev.ipynb | ||
| {% if use_uv %} | ||
| βββ pyproject.toml | ||
| {% else %} | ||
| βββ requirements.txt | ||
| {% endif %} | ||
| ``` | ||
|
|
||
| ## Key Concepts | ||
|
|
||
| ### Async ACP with the harness | ||
| The async ACP model streams events over Redis instead of an HTTP response. The | ||
| `@acp.on_task_event_send` handler spawns the Codex CLI and pushes the harness | ||
| events to the task stream. | ||
|
|
||
| ### Multi-turn memory | ||
| The codex session/thread ID is persisted via `adk.state`, so each new turn | ||
| resumes the same codex session with `codex exec resume <thread_id>`. | ||
|
|
||
| ### The unified harness surface | ||
| `CodexTurn` + `UnifiedEmitter` are the unified harness surface. The turn | ||
| normalizes CLI output into canonical AgentEx events; the emitter traces and | ||
| delivers them. | ||
|
|
||
| ## Development | ||
|
|
||
| ### 1. Choose a model | ||
| Set `CODEX_MODEL` (defaults to `o4-mini`) to control which model codex uses. | ||
|
|
||
| ### 2. Customize the subprocess | ||
| Edit `_spawn_codex` in `project/acp.py` to change the CLI flags or how the | ||
| prompt is delivered. | ||
|
|
||
| ### 3. Configure Credentials | ||
| Set your credentials via `manifest.yaml`, an exported environment variable, or a | ||
| `.env` file in the project directory. | ||
|
|
||
| ### 4. Run Locally | ||
| ```bash | ||
| export ENVIRONMENT=development && agentex agents run --manifest manifest.yaml | ||
| ``` |
Uh oh!
There was an error while loading. Please reload this page.