Run Codex
Serve Codex behind your product with streaming responses and saved sessions.
Serve a Codex agent through an HTTP API, stream its response and save its run history. This first service drafts a reply from ticket details supplied in the request. In Connect Your Tools, the agent will fetch those details through MCP.
Set up the service
Use Python 3.12 and an account with access to gpt-5.6-luna:
mkdir codex_service && cd codex_service
uv venv --python 3.12
source .venv/bin/activate
uv pip install "agno[os]" "openai-codex==0.162.1"
export OPENAI_API_KEY="your-openai-api-key"
python - <<'PYTHON'
import os
from openai_codex import Codex
with Codex() as codex:
codex.login_api_key(os.environ["OPENAI_API_KEY"])
PYTHONAn existing native CLI login can also authenticate local development. Provision and renew credentials explicitly for a deployed service. The Codex Python SDK supplies its app-server runtime; API-key login above stores authentication through the SDK.
Create the agent
Save this as harness_service.py:
from pathlib import Path
from agno.agents.codex import CodexAgent
from agno.db.sqlite import SqliteDb
from agno.os import AgentOS
workspace = Path("data/codex/workspace").resolve()
workspace.mkdir(parents=True, exist_ok=True)
db = SqliteDb(db_file="data/codex/runs.db")
agent = CodexAgent(
id="support-agent",
name="Support Assistant",
model="gpt-5.6-luna",
db=db,
cwd=str(workspace),
instructions="Answer using the supplied ticket details. Do not use tools.",
sandbox="read-only",
approval_mode="deny_all",
)
agent_os = AgentOS(agents=[agent], db=db)
app = agent_os.get_app()
if __name__ == "__main__":
agent_os.serve(app=app, host="127.0.0.1", port=7777, reload=False)SQLite keeps this local exercise self-contained. Use Postgres for deployment. The service is bound to loopback and has no caller authentication; Deploy and Operate adds the production configuration.
read-only and deny_all configure native execution permissions. They do not provision a session container; the instruction to avoid tools is behavioral guidance.
Start and call the API
Start the service:
python harness_service.pyIn another terminal, submit a streamed request:
curl -N http://127.0.0.1:7777/agents/support-agent/runs \
-F 'message=Ticket T-100: the customer asks why order O-100 has not arrived. It shipped yesterday and is due tomorrow. Draft a short reply. Do not use tools.' \
-F 'session_id=support-demo' \
-F 'stream=true'Expect SSE events containing the response, a run ID and a terminal completion event. The answer should use the supplied shipping facts. Copy the run_id from the stream to inspect its saved result:
RUN_ID="paste-the-run-id"
curl "http://127.0.0.1:7777/agents/support-agent/runs/$RUN_ID?session_id=support-demo"The result includes status, content and saved messages. This request needs no tools, so an empty tool list is expected. An error event or ERROR status is not a successful run; check provider authentication and model access before proceeding.
Continue the session
curl -N http://127.0.0.1:7777/agents/support-agent/runs \
-F 'message=Which order were we discussing?' \
-F 'session_id=support-demo' \
-F 'stream=true'Expect the agent to recall O-100. Wait for each turn to finish before submitting the next turn in that session. See Sessions and State for restart and cross-replica behavior.
Next steps
- Connect Your Tools: fetch ticket and order data through MCP.
- Configure Your Agent: instructions, permissions and native options.
- Codex cookbooks: standalone, streaming and session examples.
Add capabilities
- Structured output for validated responses.
- Images and files for attachments and their storage lifecycle.
- Retries for failure handling and idempotent tools.
- Compaction for longer conversations.
- Runs and usage for operational inspection.