GUIDE — The agent harness as a surface#
Status: law — v1, 2026-08-03 Applies to: every MCP tool response — Claude Code, Claude desktop, and any other client Parent: GUIDE.interface-principles.md Visual reference: ../mcp/ · Mechanism: relay-platform/docs/DESIGN-NOTE.mcp-rich-display.md · Contract: SPEC.mcp.md
The harness is where a large share of real Relay usage happens. It is the adjacent priority interface to mobile, not an API with nice strings — and it is designed, not emitted.
It has no pixels and it still has hierarchy, rhythm, and restraint. The same governing principle holds: display weight is proportional to information value.
Two readers, always#
Every response is read twice:
- The agent — needs to know what happened and what it can do next.
- The person over its shoulder — needs to recognise the result without decoding it.
A response that serves only the first is a state dump. One that serves only the second is prose the agent can't act on. Compose for both.
The rules#
1. Answer, then evidence#
Lead with what happened. Detail comes after, and only what's needed.
✅ "Sent — Code
HAVVPX, claimable once, expires in 7 days." ❌ A JSON object with 40 fields, three of which matter.
2. Cost less context than you save#
A response that blows the context window is a defect, not a big result. This is the harness's version of "content below the fold": an orientation call that costs more than it returns teaches agents to skip it, and an agent that skips orientation guesses.
Rules:
- Lists return counts plus a top slice, never everything.
- Bulk data offers a handle — an id, a link, a follow-up call — not the payload.
- Depth is opt-in via a parameter, not the default.
- If a response routinely exceeds a few thousand tokens, redesign the shape.
(Recorded as EXP-001: relay_context, the documented once-per-session bootstrap, returned ~98k characters — large enough that the client spilled it to a file instead of into context.)
3. Never make anyone decode an identifier#
Every id appears with its name. pc_9b8b6183e706 alone is a failure; "Relay Experience (pc_9b8b6183e706)" is fine. If the reader has to make a second call to find out what the first one returned, the first was underspecified.
4. Verbs mean one thing#
Relay has two opposite directions and they are never blurred:
| Direction | Verb | Never |
|---|---|---|
| Pull context in | claim / receive / relay in | "handoff" |
| Give context away | handoff / send / package | "claim" |
A tool's name, its description, and what it does must agree. Ambiguity here is not a copy problem; it causes wrong writes.
5. Gates where the stakes justify them#
Two-step confirmation is protection, and it is spent by overuse — a gate that fires on low-stakes calls trains agents and users to confirm reflexively, which disarms it for the call that mattered.
- Gate: irreversible, outward-facing, or destructive writes.
- Don't gate: reads, drafts, and anything trivially undone.
- A gate always says what will happen, not just "confirm?".
6. Failures and empties are answers too#
- An error names the next thing to try — never a bare code or a traceback.
- An empty result says empty, and says what would change it. "No relays match
tag:mobile" beats[]. - Never return success shaped like failure, or the reverse.
7. Progressive display, honest fallback#
Rich display is an enhancement, never a dependency. The plain-text tier must carry the full meaning on its own — a client that can't render cards is a supported client, not a degraded one. Mechanism and per-harness config live in relay-platform; what's worth showing is decided here.
Composition#
Even in plain text, structure carries meaning:
- One idea per line. A wall of prose is as unreadable as a wall of JSON.
- Codes always mono and letter-spaced — same law as the UI.
- Time relative and honest — "seen 7h ago", not a raw timestamp.
- A card is framed and consistent, so the reader recognises the shape before reading it.
- Never more than one call to action in a response. If there are three next steps, name the one that's most likely and offer the rest as options.
What the harness must never do#
- Dump raw database rows, internal ids without names, or full object graphs
- Instruct the user to do something the client can't do (the harness twin of hover-only affordances)
- Return a nudge or prompt as though it were the result of what was asked
- Bury an error inside a successful-looking response
- Repeat the same card unchanged on every call in a session
Checklist#
- Answer first, evidence second
- Response cost proportionate to value; lists are counts + slice
- Every id accompanied by a name
- Verb direction unambiguous
- Gates only where stakes justify, and they say what will happen
- Errors and empties name the next step
- Plain tier carries full meaning
- Codes mono; time relative
Framework note#
Every rule here except the claim/handoff vocabulary is generic MCP-surface design — framework-candidate, and directly relevant to Launchpad Phase 3 — Integration Surface, which takes the MCP scaffolding into core. Any product built on Launchpad will ship tools with the same two readers and the same context budget.