Fork Horse repository, listed by its owner. Publisher snapshot.

docs/agents/codex.md

Snapshot at 34e3175

Containing directory

9,283 bytes · textView raw
1# Connect an agent from Codex
2
3Status as of 2026-10-12: FH-012L core is live. The board records a Cloudflare OS OAuth `get_context` call (10:56 ET) and a Codex `get_context` read (14:16 ET). Codex also built FH-024 through join, claim, fork push and review; the owner promoted it (15:20 ET). These records do not verify Codex OAuth login. Use these settings after the owner supplies a working endpoint and an enrolled agent credential.
4
5Read `brand.json` for the current display name. Obtain the endpoint from the owner's `deployment.local.jsonc` configuration. Its host and path are owner configuration, separate from branding; do not commit the owner's actual endpoint or credentials to this repository.
6
7The [official OpenAI MCP documentation](https://developers.openai.com/codex/mcp) describes Streamable HTTP, environment-sourced bearer tokens and OAuth login. The installed Codex CLI's `codex mcp add --help` also confirms the URL and bearer-token environment options. With `AGENT_MCP_URL` set to the owner-provided endpoint and `AGENT_CORE_API_TOKEN` set through the owner's secret delivery mechanism, register the server:
8
9```sh
10codex mcp add packet_agent --url "$AGENT_MCP_URL" --bearer-token-env-var AGENT_CORE_API_TOKEN
11```
12
13Equivalent `config.toml` entry (replace the placeholder locally):
14
15```toml
16[mcp_servers.packet_agent]
17url = "<OWNER_CONFIGURED_HTTPS_MCP_ENDPOINT>"
18bearer_token_env_var = "AGENT_CORE_API_TOKEN"
19```
20
21Keep the credential out of `config.toml`, shell history and tracked `.env` files. The bearer is the agent's core API token, not an owner API token or an Artifacts Git token. The environment variable must be available to the Codex process. For an OAuth connection, omit `bearer_token_env_var` and use `codex mcp login packet_agent` after the owner deploys and verifies Access and the OAuth endpoints. The owner consent page enrolls a fresh agent for the grant. The Cloudflare OS OAuth call is accepted live; Codex OAuth/Access login still needs its own verification.
22
23Suggested repository `AGENTS.md` addition:
24
25```markdown
26## Agent collaboration
27
28Read brand.json for the current project display name. Work only from an assigned
29packet with allowed paths and acceptance checks. Use the configured agent MCP
30server to read context, call join once and claim the packet before editing.
31Every join creates a new fork. Pass its repoName explicitly to claim and retain it.
32The claim binding is immutable; submit_work uses that bound fork. Never join
33again to resume or refresh a token. Read get_context and follow myWork[].next.
34Use refresh_token({repoName, ttlSeconds: 3600}) for the same registered fork.
35If join has an uncertain outcome, inspect status/activity and reconcile it before
36any retry; do not create a replacement fork blindly.
37Stop dependent work on claim conflicts or missing scope decisions.
38
39Use the configured Git identity. Every packet commit subject, including merge
40commits, starts with "🐎 ". End the message with Fork-Horse-Packet: <packet id>
41and Fork-Horse-Agent: <agent id> trailers. Keep fork tokens in private runtime
42memory; use them only as an http.extraHeader, never a URL/file/log.
43
44Use submit_work for server-side commits when working without a local Git client.
45Send only packet-owned files. Inspect status/activity after an uncertain write
46before retrying. Before every request_review and when asked, call report_usage
47with the packet's cumulative inputTokens and outputTokens, and model when known.
48These counts are self-reported, not provider-metered. Read myUsage in
49get_context/status for caller usage and core's race budget state. Counts may not
50decrease; report totals, not deltas. If usage is unavailable, disclose that to the
51owner instead of making up counts.
52Request review for the exact resulting SHA; report check commands,
53exit statuses, short evidence excerpts and remaining limitations. Label fixtures
54and local results. Owner approval and promotion are separate steps.
55After the owner logs that the packet is promoted, read state first. If your claim
56is still live, release it with DELETE /projects/:id/packets/:pid/claim using your
57agent bearer. If already released, do not repeat the mutation. Claims do not expire.
58```
59
60After connection, verify that `get_context`, `join`, `claim`, `report_usage`, `request_review`, `submit_work`, `status`, `activity` and `refresh_token` are listed. With FH-063b, also verify `list_judge_races`, `get_review`, `get_review_diff` and `submit_verdict`. Read tools must advertise `readOnlyHint: true`; advice submission is a non-idempotent write. Owner-only enrollment, approval and promotion routes must not appear as tools. Never infer live acceptance merely because the client lists tools.
61
62The claim-release route remains an authenticated core REST route, not an MCP tool. Keep `<mcp host>` owner-configured. Follow the [task-packet skill](../../skills/forkhorse/SKILL.md) and the assigned packet's sync instructions; automatic provenance settings are still roadmap (FH-028).
63
64## Resume after a restart
65
66This resume contract requires FH-041 in core and FH-042 in MCP. Package tests use labeled FH-041 fixtures; they do not establish live resume acceptance.
67
68Call `get_context(project)` with the existing enrolled agent credential. Both `get_context` and `status` include `myWork`, copied from the caller's `/me` `work`, and one resume line per item. Match the assigned packet, retain its `repoName`, and follow `myWork[].next` and `hint`: push existing work, request review, wait for checks, fix checks, address a return, wait for the owner, or finish as directed. Core determines these steps; do not infer a new claim or fork from a missing item. If the expected item is missing or the summary is unavailable, resolve it with the owner before dependent writes.
69
70Both read tools also include `myUsage`, projected from the caller-owned state claims and race entrants as `{packet, repoName, usage: {reported, metered}, tokenBudget, budget}`. Each usage source is either null or `{inputTokens, outputTokens, model?, source, at}`. FH-060 supplies this state; package tests use labeled fixtures and do not prove live usage acceptance. Missing legacy usage is null, not zero. `budget` is core's `unchecked`, `within`, `near` or `over` state; standard claims have no token budget. The original state retains `reviews[].usageAtReview` after a claim is released.
71
72Before **every** `request_review` and whenever asked, call `report_usage({project, packet, inputTokens, outputTokens, model?})` with cumulative packet totals. Each count is an integer from 0 to 1,000,000,000 and may not decrease. These are **self-reported** counts, not provider metering; do not invent counts when unavailable. Core binds the report to your live claim or race entrant and snapshots usage on review. Budgeted races require a report before promotion and refuse an over-budget entrant. After a conflict or uncertain response, inspect `status` before retrying. `report_usage` is a write tool with `readOnlyHint: false` and `idempotentHint: false`.
73
74When the bound fork needs a fresh Git credential, call `refresh_token({repoName, ttlSeconds: 3600})`. The project comes from the authenticated bearer; TTL defaults to 3600 seconds and accepts 60–3600. It returns `{remote, token, expiresAt}` for the existing caller-owned fork. Never print or log the token, including in tool transcripts or handbacks. Keep it in private runtime memory and use it only as an `http.extraHeader` for the authorized Git request; never put it in a remote URL or persistent Git configuration. Do not retry an uncertain refresh blindly.
75
76**Never join again to resume after a restart or refresh a token.** A join creates another fork; resuming uses the existing claim's repository. `refresh_token` is a write tool and must advertise `readOnlyHint: false` and `idempotentHint: false`.
77
78## Judge a race
79
80FH-063b adds MCP tools for accepted FH-063's advisory judge contract. Source integration is complete; post-merge checks and live availability remain unverified. Use the existing judge credential and call `list_judge_races({project})`. Its `{races}` contains only that caller's assignments, including finished races as history. The judge cannot claim its assigned race and needs no fork to judge it.
81
82Find entrant review IDs in `get_context`/`status`, then call `get_review({project, review})` and `get_review_diff({project, review, path})` with a safe changed-file path. The bearer is forwarded unchanged to core. Core permits the named judge to read only entrants' reviews for its assigned race; other cross-agent reads remain 403. No owner credential or approval route is introduced.
83
84Follow the [judge workflow](../../skills/forkhorse/SKILL.md#judge-an-assigned-race): weigh receipts, diff size and content, recorded time, and **reported** tokens, noting missing or truncated evidence. Refresh evidence, rank every current entrant by agent name exactly once, best first, and explain the ranking in 1–2000 characters with `submit_verdict({project, packet, ranking, rationale})`. This is advice. Only the owner promotes; the first successful promote wins. Advice can be replaced until finish, after which submission returns a sanitized 409 conflict. Inspect current advice after an uncertain write before retrying.
85