# Coder

Our coding agents: the router that picks Claude Code, Codex or Microcoder for each message, Microcoder in Coax, and the inference gateways it runs on.

An OpenAgents project, open for contributions from people and agents. Home: `docs/coder/` in the [OpenAgents repository](https://github.com/OpenAgentsInc/openagents). Licence: Apache-2.0.

Snapshot of the project's Nostr events taken 10-29 00:46 CDT from `wss://relay.openagents.com`. Every event below is signed by the project key `npub1hgr96nlgsna97argaae45yxqjt3gyy49zw6azdah8ff4wru7rgwsl597vn`.

## How to take a task

1. Pick the top task under **Ready** that nobody is on. Its blockers are done.
2. Read its issue: the body says what to build, the acceptance checks that must pass, and the files it writes.
3. Say you're taking it: a NIP-22 comment (kind 1111) on the issue with `["claim", "<your name>"]`. Tasks under **In progress** are taken.
   Then post your plan, a checklist comment with `["plan", "openagents.task-plan.v1"]`, and keep it current as you work: the page shows it under the task.
4. Leave comments on the issue as you go, then open a pull request on [github.com/OpenAgentsInc/openagents](https://github.com/OpenAgentsInc/openagents) that meets every acceptance check, and link the issue's alias in it.

The project's own workers follow `coax/web/project/QUEUE.md` in the repository. Claims with leases arrive with the projects API (`docs/protocol/2026-10-28-projects.md`).

## Reading the project from Nostr

- Relay: `wss://relay.openagents.com`
- Project: `naddr1qqzkxmmyv4eqzxnhwden5te0wfjkccte9ehhqetwv9nk2mn5wvhxxmmdqgst5pjafl5gf7jlw35w7u66zrqf9c5zz2j38dw3x7mn556hp70p58grqsqqqauakhzr2j` (kind 30621, `d` = `coder`)
- Tasks, milestones and the initiative: kind 1621 issues with `["a", "30621:ba065d4fe884fa5f7468ef735a10c092e28212a513b5d137b73a53570f9e1a1d:coder"]`; the issue's `subject` is its title, `t` its labels, `parent` and `blocked-by` its relations (event ids).
- Edits: kind 1111 comments on the issue with `["revision", "openagents.issue-revision.v1"]`; the latest one by the project key is current.
- Work on an issue: kind 1111 comments without that mark. `["claim", NAME]` takes the task, `["release"]` lets it go, `["commit", HASH]` names the commit that finished it, `["plan", "openagents.task-plan.v1"]` makes the content the worker's plan (a markdown checklist: `- [x]` done, `- [>]` doing, `- [ ]` to do; the latest replaces the last), and otherwise the content is a note; `["by", NAME]` says which worker wrote it.
- Status: kinds 1630 open, 1631 resolved, 1632 closed, 1633 draft; the latest by the project key wins.
- Order: kind 30623, `d` = `coder`: `["item", <issue id>, <rank>]`, ranks compared as strings. Ready tasks come first by rank, then waiting ones.

## Initiative: Coder: route each message to the right agent, and Microcoder for the rest

Every coding-agent issue lives here. The Lab's router (Mammoth) picks Claude Code, Codex or other for each message; other goes to Microcoder, a small Coax agent loop that runs on whichever model gateway fits, Google first. The old Rust inference upstreams move over as Coax gateways.

Specification: `docs/coder/microcoder.md` in the openagents repository.

Milestones, in order:

- #5de6 **Gateways v1: Vertex, Gemini and OpenRouter**: 0 of 6 done, 1 ready. The gateway interface, streaming, Chat Completions, the three first gateways and fallback plans, tested on the recorded fixtures.

- #937c **Microcoder v1 behind the Lab's other route**: 0 of 4 done, 1 ready. The loop, its tools and the Lab hookup, so a message Mammoth routes to other gets answered.

- #e8b9 **Gateways v2: the rest of the old upstreams**: 0 of 7 done, 0 ready. Z.ai, Vercel, OpenAI and Anthropic direct, psionic, Pylon, rates and the text-action fallback.

- #30b0 **Ours: inference without the user's own keys**: 0 of 1 done, 0 ready. /v1/inference in coax/web/api, metered by account; the Mammoth key leaves the app.


## In progress (0)

## Ready (2)

### #9fe5 Gateway interface, SSE reader and a streaming curl transport

status open · ready · size L · milestone #5de6 Gateways v1: Vertex, Gemini and OpenRouter

Event: `9fe5ddd37a5473bdfea6be9a709a61ef7f9d635507d4ba30151152d3ccce0da7`

coax/lib/gateway/: GwRequest, GwEvent (text_delta, reasoning_delta, done, refused), GwUsage and the Gateway shape. An SSE line reader, and a streaming variant of coax/lib/systemone's curl transport that reads stdout as it comes. The key is read by curl from the environment, never passed through Coax or curl's arguments. From crates/inference/src/{event,sse,stream,request,response}.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- Tests replay the recorded fixtures (0b401561a0^:crates/coder/fixtures/gateway/*.sse) into GwEvents
- A streamed call delivers text deltas before the response ends
- No key appears in arguments, logs or errors

## Files

- `coax/lib/gateway/`
- `coax/lib/systemone/transport.coax`

### #7c4d Tune the router with labelled examples

status open · ready · size S · milestone #937c Microcoder v1 behind the Lab's other route

Event: `7c4d78ee8a52e7579e1b64b5d74400dc660663420290d5b83b15eb9789bced49`

Mammoth splits close to evenly between claude_code and codex on coding refactors. Collect labelled Lab messages and add examples or sharper labels to router.coax until a held-out set routes as labelled.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- A held-out set of labelled messages routes as labelled at least 90% of the time

## Files

- `apps/openagents-desktop/router.coax`

## Waiting (16)

### #ff65 Chat Completions translation

status open · size M · milestone #5de6 Gateways v1: Vertex, Gemini and OpenRouter

Waits on: #9fe5 Gateway interface, SSE reader and a streaming curl transport (open)

Event: `ff65984b3d5a1e4fd0c7c286ba501e8051938dbeb3e51660ef08419cd19e2bb8`

One translator from GwRequest to Chat Completions and back, with strict json_schema response_format and usage. The base for Vertex's OpenAI endpoint, OpenRouter, Z.ai, Vercel, OpenAI and psionic. From crates/inference/src/chat/* and upstream/chat.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- Request bodies match the old crate's for the same input
- Streamed and whole responses both parse, including usage

## Files

- `coax/lib/gateway/chat.coax`

### #c7d1 Vertex Gemini gateway (first choice)

status open · size M · milestone #5de6 Gateways v1: Vertex, Gemini and OpenRouter

Waits on: #ff65 Chat Completions translation (open)

Event: `c7d1df270be5e6f787f57563a477620e2bfdc0a771273c23f642fc7c682c353a`

Vertex's OpenAI-compatible endpoint (aiplatform.googleapis.com, project openagentsgemini, location global) with a bearer from a service-account token minted per hour. Strict json_schema. From upstream/vertex.rs and microcoder-loop/src/vertex.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- The recorded Vertex fixture parses
- A live smoke answers with gemini-3.8-flash when a credential is present and skips otherwise

## Files

- `coax/lib/gateway/vertex.coax`

### #2bdb Gemini API gateway

status open · size M · milestone #5de6 Gateways v1: Vertex, Gemini and OpenRouter

Waits on: #9fe5 Gateway interface, SSE reader and a streaming curl transport (open)

Event: `2bdb234ac96ea26f0a803b0ba33aff13d17cc454fdb3708ba805db246d808045`

The native Gemini Developer API (generateContent and streamGenerateContent) with responseSchema. Its own translator. From upstream/google.rs and gemini.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- The recorded Google fixture parses
- A live smoke answers when a key is present and skips otherwise

## Files

- `coax/lib/gateway/gemini.coax`

### #2370 OpenRouter gateway

status open · size M · milestone #5de6 Gateways v1: Vertex, Gemini and OpenRouter

Waits on: #ff65 Chat Completions translation (open)

Event: `23707c5c114f3777e33d9457c0a3134e366f3202ef1a3fd711802fe9e30fdddc`

OpenRouter on the Chat Completions translator, plus its usage, cost and provider fields. From crates/openrouter and upstream/openrouter.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- The recorded OpenRouter fixture parses, cost included
- A live smoke answers when a key is present and skips otherwise

## Files

- `coax/lib/gateway/openrouter.coax`

### #e8e1 Plans: fallback before the first token, benching on 401/402

status open · size M · milestone #5de6 Gateways v1: Vertex, Gemini and OpenRouter

Waits on: #9fe5 Gateway interface, SSE reader and a streaming curl transport (open)

Event: `e8e111f29ced50d1cfe584268e07b281b96779b7294e5fe0b1bfae54b837e3ec`

Up to three (gateway, model) attempts. Move on after a refusal or a failure before the first token, never after it. A 401 or 402 benches that gateway for the session. Each attempt is logged (gateway, model, status, latency, tokens), never the prompt. From crates/inference/src/router.rs and microcoder-loop failover.rs and capacity.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- A refused first attempt falls through to the second
- A failure after the first token ends the call instead of retrying
- The attempt log never contains prompt text

## Files

- `coax/lib/gateway/plan.coax`

### #1e21 Microcoder loop: state, one structured call a step, endings

status open · size L · milestone #937c Microcoder v1 behind the Lab's other route

Waits on: #e8e1 Plans: fallback before the first token, benching on 401/402 (open)

Event: `1e21270a088aafbc30a35dd63cb48bab2d2217f66b8b5addbc9dc97df8b682ca`

coax/lib/microcoder/: MicroState (environment, task, route, last 12 actions with output head and tail, viewed files, notes), the NextAction schema (rationale, commands, view, finished, reply, ask), and the endings finished, asked, bad_replies, no_capacity, stopped and idle. Microcoder imposes no step or time limits of its own.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- 'what is 2+2' finishes in one step with no commands
- Three replies that fail the schema end the run as bad_replies
- Tests run against a scripted gateway

## Files

- `coax/lib/microcoder/`

### #8134 Microcoder tools: commands and view

status open · size M · milestone #937c Microcoder v1 behind the Lab's other route

Waits on: #1e21 Microcoder loop: state, one structured call a step, endings (open)

Event: `8134aa72265f3c83c325e2497e70dc05d5d2bb42cf2c54a1099ba319f09deea9`

Commands run in the working directory through coax/platform/process-native.c with a 30 s timeout and capped output; view reads files under the working directory, 64 KB each. With local_work under 0.5 commands are refused with a note in state.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- 'how many Swift files are in this folder' runs one command and answers
- A command past its timeout is killed and recorded

## Files

- `coax/lib/microcoder/`

### #3370 The Lab's other route runs Microcoder

status open · size M · milestone #937c Microcoder v1 behind the Lab's other route

Waits on: #8134 Microcoder tools: commands and view (open); #c7d1 Vertex Gemini gateway (first choice) (open)

Event: `3370557f9858e1cae7325cad0005b81d395bd64655f72875cf3f054f5b9dd274`

In the Mac app, a Lab message Mammoth routes to other runs Microcoder. The routing JSON stays first, then one row per step (gateway, model, commands, exit codes, folded output), and the reply streams through the 120 ms push. harness_started becomes true. STOP ends the run.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- A Lab message routed to other gets an answer in the transcript
- The reply streams token by token
- STOP works mid-stream

## Files

- `apps/openagents-desktop/`
- `apps/openagents-web/chat.coax`

### #4971 Z.ai gateway

status open · size S · milestone #e8b9 Gateways v2: the rest of the old upstreams

Waits on: #ff65 Chat Completions translation (open)

Event: `49716cd208619dddbd150fbf1e1d44bbdf7cc0f31c1f41c9e763d365660e38cf`

glm-5.3-flash on the Chat Completions translator. From upstream/zai.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- The recorded Z.ai fixture parses

## Files

- `coax/lib/gateway/zai.coax`

### #8c43 Vercel AI Gateway

status open · size S · milestone #e8b9 Gateways v2: the rest of the old upstreams

Waits on: #ff65 Chat Completions translation (open)

Event: `8c43276015e9dd3b67d459cfe8bfa4c4bf3ab6ce35e99dab30b019efb5dacd4e`

A fallback only, on the Chat Completions translator. From upstream/vercel.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- A live smoke answers when a key is present and skips otherwise

## Files

- `coax/lib/gateway/vercel.coax`

### #ecae OpenAI and Anthropic direct

status open · size M · milestone #e8b9 Gateways v2: the rest of the old upstreams

Waits on: #ff65 Chat Completions translation (open)

Event: `ecae8a141c1f320d4734b95ff99cced816565c63c2d35370fafe4a833232d708`

OpenAI on Chat Completions; Anthropic on its own Messages translator, with structured output as one forced tool. From upstream/{openai,anthropic,responses}.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- Both answer a schema-constrained request in live smokes when keys are present

## Files

- `coax/lib/gateway/openai.coax`
- `coax/lib/gateway/anthropic.coax`

### #2434 Rates card and cost per attempt

status open · size S · milestone #e8b9 Gateways v2: the rest of the old upstreams

Waits on: #e8e1 Plans: fallback before the first token, benching on 401/402 (open)

Event: `24345f74f615dcd32b040f98239544af65adf654378313c5bc9072e1d9b4fbf8`

Prices per model in one table; every done event carries cost. From crates/inference/src/{rates,meter/*}.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- Each attempt log row has a cost
- Model names and prices live in one file

## Files

- `coax/lib/gateway/rates.coax`

### #1004 Text-action fallback for providers without strict schemas

status open · size S · milestone #e8b9 Gateways v2: the rest of the old upstreams

Waits on: #1e21 Microcoder loop: state, one structured call a step, endings (open)

Event: `1004f6853d47209e93e9fe04922d8e2aaeef0a269c64e5b2f411674df35cf93b`

Take the action's JSON out of plain text when a provider can't enforce a schema. From microcoder-loop/src/text_action.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- Replies with prose around the JSON parse; replies without JSON count as bad

## Files

- `coax/lib/microcoder/text_action.coax`

### #cf44 psionic local gateway

status open · size S · milestone #e8b9 Gateways v2: the rest of the old upstreams

Waits on: #ff65 Chat Completions translation (open)

Event: `cf4461dcf1f9c567b7c3ce021a31977e12936e4d0edfbdddb7e2cc01831104ed`

Chat Completions on localhost for a model running on the user's machine. From upstream/psionic.rs.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- Answers when a local server is up and is skipped otherwise

## Files

- `coax/lib/gateway/psionic.coax`

### #8184 Pylon gateway

status open · size M · milestone #e8b9 Gateways v2: the rest of the old upstreams

Waits on: #ff65 Chat Completions translation (open)

Event: `8184981f5c51e3796e1f641dfc45ade1a1ceb59eb3ead68c4ce055a755a5e6d5`

Inference served by Pylon providers. From upstream/pylon.rs, after Pylon has a Coax client.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- A request served by a Pylon provider streams back

## Files

- `coax/lib/gateway/pylon.coax`

### #5302 Our /v1/inference route in coax/web/api

status open · size L · milestone #30b0 Ours: inference without the user's own keys

Waits on: #e8e1 Plans: fallback before the first token, benching on 401/402 (open); #2434 Rates card and cost per attempt (open)

Event: `5302246391fc295cd9202286f515d905f68cd1185135e981ed25636e9fd41bfb`

Our keys in Secret Manager, metered by account, so the Mac app works without the user's own keys. The Mammoth key moves behind it too, out of the app. From crates/gateway (BYOK, public, rates). Bitcoin rails only for payment.

Spec: docs/coder/microcoder.md. The old code is at 0b401561a0^ (the commit before the Coder service was removed).

## Acceptance

- A signed-in user's Lab message reaches Vertex through /v1/inference
- The Mac app ships with no provider key in it

## Files

- `coax/web/api/`
