A typed stitch replaces fetch
StitchAPI turns one endpoint — or one example — into a declarative, validated, observable unit of work. Define it once; call it as a function, a CLI, an HTTP route, or an MCP tool. Humans and agents get a capability, not a credential.
// Declare once — types, validation, retries, drift.
const listWebsites = stitch({
path: '/api/websites',
output: Website.array(), // response contract → drift
auth: session, // capability, not a secret
retry: { attempts: 3, on: [429, 503] },
});
// Call it — awaitable and streamable.
const sites = await listWebsites();
for await (const ev of listWebsites.stream()) {
// start → progress → drift → result → done
}fetch was built for a browser, not a model reasoning over results
A stitch returns an async iterable of typed events instead of Promise<bytes> — one shape that generalizes HTTP progress and pagination today, and LLM token streaming tomorrow.
Define the stitch once. Reach it four ways.
The same typed unit is a function, a CLI command, an HTTP route, and an MCP tool — so humans and agents call exactly the same validated, observable thing.
In-process function
await listWebsites()Import the stitch and call it like any typed function — awaitable or streamable.
CLI command
$ stitch list-websitesRun the same definition from a shell or a script, no app boot required.
HTTP endpoint
GET /list-websitesServe a stitch as a route — validated in, validated out, traced by default.
MCP / agent tool
tool: list_websitesAgents invoke it directly and receive a capability — never the underlying secret.
Everything fetch left to you — declared, defaulted, and observable
Progressive disclosure: stitch('https://…') just works, and every capability reveals its knobs only when you reach for them.
Runtime drift detection
Every response is validated against its contract, so a vendor silently renaming a field surfaces immediately — not hours later as a downstream undefined.
Validation, then re-prompt
Schemas guard params, query, body, and output. On a mismatch the stitch can re-prompt instead of handing garbage back to a model.
Reliability built in
Retries with backoff + jitter, Retry-After, idempotency keys, throttling, and circuit breaking — declared per stitch, not bolted on.
Layered timeouts
Total, step, and chunk timeouts plus AbortSignal, so a slow upstream never quietly hangs your call.
The event stream is the spine
start → progress → drift → result → done. Streaming output, observability, and drift all read the same stream a stitch emits.
Capability, not credential
Auth lives at the stitch. Callers — including agents — get data without ever seeing the secret behind it.
Compose, don’t configure
baseUrl, auth, retry, throttle, and hooks are named, shareable values you compose with .with() and extends — no central config object.
Observable by default
gen_ai.* and mcp.* spans carry tokens, cost, and latency, turning the agent-native layer into your integration-health layer.
A per-call primitive — not a workflow engine or an iPaaS platform
The stitch is the boundary, and nothing more. Orchestration, queues, and business state stay your app’s job — that restraint is the point.
Spec-less long tail
Every serious competitor needs an OpenAPI spec. A stitch needs one endpoint — or one example. Author from the response you already have.
Heterogeneous & agent-native
A lightweight library where HTTP, GraphQL, shell, and LLM are symmetric, declared primitives — kind-agnostic today, composable into bigger stitches tomorrow.
Replace fetch. Start with one endpoint.
Declare your first stitch and call it as a typed function in five minutes — then reach the same definition from the CLI, HTTP, or an agent.