Guide
Build an adapter with a coding agent
An adapter is the only place where a WMOS message becomes a specific system action. This guide is the brief to give a coding agent: what it may change, what it must prove, and how to reject work that only looks finished.
What the adapter owns
The adapter translates between a message and a system API. It owns the interpretation, the permission check, the approval path, retries, and the record of what it touched.
It does not own routing, grants, or the model choice. Business logic inside the router is a defect, not a feature: it makes one system's rules everyone's rules.
What the agent must be given
A coding agent without the contract will invent one. Hand it these inputs, and nothing else it does not need.
spec/ADAPTER_COMMON.md— responsibility boundary (§3), router HTTP/SSE envelope (§7), canonical request/reply (§8)spec/adapter-contract.test.mjs— the isolated contract test; no network, no modeladapters/router-a2a-v1/— a reference adapter to read, not to copy blindlyadapter-kit/— a runnable skeleton with seven contract tests to start from- The target system's API documentation and its real permission model
- The seat id and where the credential comes from at runtime — never the value in the repository
Six steps, in order
Each step produces evidence. If a step has no evidence, the next step is not allowed to start.
- 1. Inventory the system: endpoints, auth, rate limits, what a failed call leaves behind
- 2. Write the mapping: message field → API call, and the reverse for the result
- 3. Implement the adapter behind that mapping, with one visible entry point
- 4. Pass the local contract test, including the rejection cases
- 5. Run a local smoke against a test router: send, receive, return, ACK, retry
- 6. Review: no secrets, no router edits, failure path demonstrated, approval path intact
The brief to copy
This is the working brief we use. Replace the bracketed parts; keep the constraints.
Role: build one WMOS adapter for [system].
Read first: spec/ADAPTER_COMMON.md §3, §7, §8; adapter-kit/README.md; adapter-kit/test/adapter.test.mjs.
Allowed files: adapters/[name]/**, test files for that adapter.
Forbidden: router-core/**, packages/routing-contract/**, spec/**, any credential value.
Rules:
- The router forwards envelopes; do not add business logic to it.
- Deduplicate by job_id; do not infer a destination from a message body.
- A result is success only with real system output. Timeouts are error or blocked.
- Never log credentials or full customer payloads.
Done when:
- node --test spec/adapter-contract.test.mjs passes
- the local smoke covers send -> receive -> result -> egress ack -> retry
- failure path (API down, duplicate, timeout) is shown in output
Report: files changed, raw test output, the failure path, and open risks.
The last line matters. A report without raw output is a claim, not evidence.
Definition of done
Reject the work if any line is missing. These are the checks that catch an adapter which compiles but cannot be operated.
- Contract test passes, including malformed and rejected messages
- Duplicate job delivery does not repeat the side effect
- Timeout and API failure produce
errororblocked, neversuccess - The result is submitted for the correct
job_id, so the router's correlation and original request binding stay intact - Seat credential is read at runtime from the environment or secret store
- Logs contain no credential and no full customer payload
- The adapter does not modify router code to make a test pass
- A human approval step exists where the system action is irreversible
Failure modes to look for in review
These are the patterns we see most often when an agent is asked to build an adapter without constraints.
- Payload parsing pushed into the router, so one system's schema becomes global
- Destination guessed from the body instead of the stored binding
listenevents answered with a result they do not own- Deduplication by arrival order instead of
job_id - Success reported from the model's text rather than the system's response
- Credential pasted into a config file, a test fixture, or a log line
- Retry that repeats an irreversible action
- A test that asserts the adapter's own output instead of the contract
How to judge the result
Read the diff, then the raw output, then the failure path. If the agent cannot show a failing case handled correctly, the adapter is not done — it is a happy-path demo.
This is also why the work is reviewable at all: the contract is external to the agent's opinion of its own code.