One call shape
Seed apps talk to a daemon through a universal client with a single call shape: request(key, input) → output. The key names a method — Resource, Query, Search, ListComments — and each method has its own input and output. Historically those shapes lived only in TypeScript. Now each one is a published schema.
The catalog
Each method is a seed-rpc-<method> schema: a closed map with three properties. key is a string restricted by enum to the one method name, so the schema is self-identifying. input references the schema of what you pass. output references the schema of what comes back — often a union with null for "not found". For example, RPC: Query pins key = "Query", takes a hypermedia-query — the same shape a Query block embeds in a document — and returns a seed-query-result or null.
seed-rpc is the union of every method. That one schema is the machine-readable table of contents for the API. A few of its variants:
method | input | output |
|---|---|---|
a parsed id (seed-id) | a seed-resource: document, comment, redirect, not-found, tombstone, or error | |
a document query | the matching documents with their metadata | |
a query string, plus optional account scope, filters, and paging | ||
a target seed-id | ||
a target seed-id | a | |
an account |
Open the union page for the full list; every variant links to its own page with its exact fields.
The read models
The output side is built from the seed-* read models: the derived data the daemon computes for clients, as distinct from the signed blobs that travel the network. seed-document is a document with its versions, authors, and timestamps already resolved; seed-id is the parsed form of an hm:// identifier; seed-interaction-summary counts the comments, citations, and changes on a resource. The signed blobs are covered in Onyx on the Hypermedia Network; the read models are the other half of the picture — what you actually receive.
The console
In the Seed app, with Developer Mode on, open the schema tour and navigate to any seed-rpc-* page: below the schema is a live call section for that method. The input is edited with the same schema-respecting value editor used everywhere else — seeded with the method's required fields, with dropdowns and reference pickers where the schema calls for them. Press Run and the app sends the request through the real universal client, then validates the response against the declared output schema, showing matches schema or listing the fields that did not conform. The seed-rpc page renders the whole console, with a method picker built from the union.
None of that is hand-wired. The console reads the seed-rpc union at runtime, so a method exists in the console exactly when its schema exists in the library.
Why type the API
For people exploring: the console is an executable reference. Every field is documented at the point you fill it in, and every response is checked against what was promised.
For agents and tools: a method's contract is a resolvable document. An agent can read seed-rpc-search, construct a valid input, and know the shape it will get back — the same discipline a tool contract gives, applied to the platform itself.
For the codebase: the generated TypeScript types for each read model come from these schemas, so the client, the tests, and the documentation cannot drift from each other.
For catching drift: if the daemon's response ever stops matching its schema, the console shows it in red. The schema is a living assertion about the API, not a description written once.
Adding a method
Add a seed-rpc-<method>.json with its key enum, input, and output; add a companion .md; reference it from the seed-rpc union; run the publisher to update the lockfile and the generators to refresh the bundled registry and TypeScript types; sync. The method then appears in the console, in the tour, and as a typed call in the client — from one schema. The pipeline is described in how Onyx works.
Do you like what you are reading? Subscribe to receive updates.
Unsubscribe anytime