| name | tester-agent |
| description | Use when the user asks Codex to read or write Odysseus-compatible data (todos, email, calendar, memory, documents) or to launch/monitor/stop a Cookbook model-serve task through the scoped Codex Agent API. Requires TESTER_AGENT_URL and TESTER_AGENT_API_TOKEN, with ODYSSEUS_URL and ODYSSEUS_API_TOKEN supported as fallback. |
Tester Agent
Use this skill when a user asks to interact with an Odysseus-compatible service from Codex through the copied Tester Agent mode.
Configuration
Expect these environment variables:
TESTER_AGENT_URL: Base URL for the service, for example http://127.0.0.1:7000.
TESTER_AGENT_API_TOKEN: Scoped API token created in the service settings for a Codex-style agent.
The helper also accepts Odysseus-compatible fallback variables:
ODYSSEUS_URL
ODYSSEUS_API_TOKEN
If both variable pairs are missing, do not guess credentials. Tell the user to create a scoped agent token in the service settings and expose the URL and token to the terminal session.
When to use what
- Reminder ("remind me at 5pm to do X") -> TODO with
due_date. The due date is the reminder; it fires through the user's configured channel. Do not create a calendar event for a reminder.
- Calendar event ("meeting at 3pm", "dentist Tuesday 10am") -> calendar event. Use for scheduled blocks, meetings, appointments, recurring schedules, and time ranges.
- Note or freeform info ("note that the wifi password is ...") -> memory or todo without a due date, depending on whether it is a fact or action item.
- Persistent fact or preference about the user -> memory.
If the user says "reminder" plus a time, default to TODO with due_date. Only switch to calendar if the user explicitly says "calendar", "event", "meeting", "appointment", or describes a time range.
Safety
- All data access must go through the scoped HTTP API under
/api/codex/*.
- Check
/api/codex/capabilities before using a tool surface.
- Treat
403 as an intentional settings restriction. Do not work around it.
- Do not use SSH, Docker, direct Python imports, SQLite queries, MCP internals, browser cookies, or local files to read/write service data.
- Do not call helper internals such as
do_manage_notes, email MCP internals, or database sessions directly for user data, even if shell access exists.
- Never send email directly unless the user explicitly asks to send and the token has a send-capable scope.
- Keep actions scoped to the token owner.
Todos
The scoped API supports todos/checklists:
GET /api/codex/todos
POST /api/codex/todos
Use the bundled helper script when available:
python3 tester-agent/scripts/tester_agent_api.py capabilities
python3 tester-agent/scripts/tester_agent_api.py todos list
python3 tester-agent/scripts/tester_agent_api.py todos add "Follow up"
Supported todo actions are list, add, update, delete, and toggle_item.
For reminders, send due_date in the body via the generic POST so the time becomes a structured reminder:
python3 tester-agent/scripts/tester_agent_api.py POST /api/codex/todos '{"action":"add","title":"Call dentist","due_date":"tomorrow at 5pm"}'
The backend accepts ISO timestamps and natural language like "tomorrow 5pm", "next Monday 9am", and "in 2 hours". It anchors to the user's timezone.
Email
The scoped API supports email reads:
GET /api/codex/emails?folder=INBOX&limit=10&offset=0&filter=all
GET /api/codex/emails/{uid}?folder=INBOX
Use the bundled helper script when available:
python3 tester-agent/scripts/tester_agent_api.py emails list 5
python3 tester-agent/scripts/tester_agent_api.py emails read UID
If /api/codex/capabilities does not show email.read: true, do not inspect email. Ask the user to enable Email read in the agent settings.
Memory
GET /api/codex/memory lists memories for the token owner.
POST /api/codex/memory creates memory. Body: {"text": "...", "category": "fact", "source": "user", "session_id": null}. Requires memory:write.
DELETE /api/codex/memory/{memory_id} removes a memory entry. Requires memory:write.
python3 tester-agent/scripts/tester_agent_api.py GET /api/codex/memory
python3 tester-agent/scripts/tester_agent_api.py POST /api/codex/memory '{"text":"User prefers SI units","category":"preference"}'
Calendar
GET /api/codex/calendar/events?start=ISO&end=ISO lists events in a window.
POST /api/codex/calendar/events creates an event. Body matches EventCreate: summary, dtstart, dtend, all_day, description, location, calendar_href, rrule, color. Requires calendar:write.
DELETE /api/codex/calendar/events/{uid} deletes an event by returned UID. Requires calendar:write.
Documents
GET /api/codex/documents?search=...&limit=50 lists the document library.
GET /api/codex/documents/{doc_id} fetches one document.
POST /api/codex/documents creates a document. Body: {"session_id": "...", "title": "...", "content": "...", "language": "markdown"}. Requires documents:write.
DELETE /api/codex/documents/{doc_id} deletes a document. Requires documents:write.
Email draft and send
POST /api/codex/emails/draft creates a draft. Body matches SendEmailRequest: to, cc, bcc, subject, body, body_html, attachments, account_id, in_reply_to, references. Requires email:draft or email:send.
POST /api/codex/emails/send sends email with the same body. Requires email:send. Never send without explicit user instruction.
Cookbook serve
The Cookbook surface reproduces what a human would do in the app: read running serves, tail task output, edit the launch command, relaunch, and stop a stuck serve. Use this when the user is debugging a model server that will not come up.
GET /api/codex/cookbook/tasks lists active serve/download/install tasks. Requires cookbook:read.
GET /api/codex/cookbook/servers lists configured servers. Requires cookbook:read.
GET /api/codex/cookbook/cached?host=<NAME> lists models already cached on a named server. Call before serve. Requires cookbook:read.
GET /api/codex/cookbook/presets lists saved serve presets. Prefer a saved preset before composing a new command. Requires cookbook:read.
GET /api/codex/cookbook/output/{session_id}?tail=400 reads persistent task logs or the tmux pane fallback. Requires cookbook:read.
POST /api/codex/cookbook/serve launches a serve task. Body: { repo_id, cmd, remote_host?, ssh_port?, env_prefix?, gpus?, platform? }. The command leading binary must be allowlisted by the service. Do not prefix with cd, source, shell chaining, or command substitution. Requires cookbook:launch.
POST /api/codex/cookbook/preset/{name} launches a saved preset by name. Requires cookbook:launch.
POST /api/codex/cookbook/adopt registers an externally-launched tmux session into Cookbook tracking. Body: { tmux_session, model, host?, port? }. Requires cookbook:launch.
POST /api/codex/cookbook/stop/{session_id} kills the tracked tmux session. Requires cookbook:launch.
python3 tester-agent/scripts/tester_agent_api.py cookbook tasks
python3 tester-agent/scripts/tester_agent_api.py cookbook output serve-abc12345 400
python3 tester-agent/scripts/tester_agent_api.py cookbook stop serve-abc12345
python3 tester-agent/scripts/tester_agent_api.py cookbook serve \
/mnt/HADES/models/Qwen3.5-397B-A17B-AWQ \
"vllm serve /mnt/HADES/models/Qwen3.5-397B-A17B-AWQ --host 0.0.0.0 --port 8001 --tensor-parallel-size 8 --max-model-len 262144 --gpu-memory-utilization 0.90 --dtype auto --max-num-seqs 8 --trust-remote-code --enable-expert-parallel --enable-auto-tool-choice --tool-call-parser qwen3_coder --reasoning-parser qwen3" \
pewds@192.168.1.12
Debug loop pattern: tasks -> output SID 600 -> stop SID -> serve repo "new cmd" -> wait -> output on the new session ID.
Hard limits this surface enforces:
cookbook serve command allowlist plus shell-metacharacter rejection.
cookbook stop requires session IDs matching [a-zA-Z0-9_-]+.
- The agent can spawn GPU-pinning long-lived processes; stop the previous attempt before relaunching.
Forbidden bypass pattern
If you are about to reach the host/container, import app internals, query the database, read local app files, or call MCP helper modules directly, stop. Those paths bypass settings and token scopes. Ask the user to enable the relevant agent tool toggle instead.