An agent is just a program that calls a model. Fascicle hands you the pieces to write that program yourself: every LLM call, tool, and plain function is a Step<i, o>, and steps snap together into whatever shape your problem actually has. No magic. Just logic.
Most agent libraries are frameworks — they own your control flow, hide it behind decorators, and tie you to one vendor. Fascicle is the opposite: a small set of plain, typed functions you compose yourself. You keep the architecture; it just makes the hard parts composable. Bigger frameworks will always ship more integrations; fascicle competes on a different axis: controllability, auditability, and portability.
Develop against a free local model on your laptop; ship the same flow on Bedrock, Anthropic, or OpenAI by changing a string, not your code. Eight transports sit behind one generate, and the local-to-hosted path is proven in production.
No decorators, no dependency injection, no framework lifecycle, no ambient scheduler that decides when your code runs. A flow is plain functions you can read top to bottom, set a breakpoint in, and unit-test.
No hosted control plane, no vendor runtime, no dashboard-first product. Adapters are injected per run, every peer is optional, and a Step drops into the code you already have. No rewrite, no buy-in.
Every primitive takes a Step<i,o> and returns a Step<i,o>. Wrap one in retry, fallback, or ensemble_step and it's still just a step — behavior layers on, the type never changes.
The harness is the product. The model is a service it calls. Your outer program is ordinary, deterministic code that you can read, test, and reason about — it reaches for a model only where real judgment is needed, and runs token-free everywhere else.
That's the opposite of handing the reins to a model and hoping it orchestrates the others. Real engineering lives in the harness — Fascicle just gives you the primitives to compose it. Even the frontier labs now state the equation plainly: an agent is a model plus a harness, and the harness is the durable, controllable part.
model_step turns a model role into a Step<i, o> that returns the answer itself: a string, or the schema-validated value. Every primitive you've already seen applies to it. Wrap it in retry, fan it out with map, race it with fallback. Fascicle doesn't offer a second API for “calling a model carefully.” When the caller wants the envelope (usage, cost, tool calls), model_call takes the same config and returns the full GenerateResult.
It also threads the tedious parts for you (cancellation through ctx.abort, tracing through ctx.trajectory, and streaming chunks), so your flow stays pure composition and never imports a provider SDK.
Read the concepts →Because every composer takes a Step and returns a Step, a composition is just another Step. No layer is privileged as a “top level,” and no interface widens as a flow grows — a thousand nested layers still type as Step<i, o>.
So you harden a flow the way you'd wrap a function. Need retries, a fallback, or three-model voting? Wrap the step you already have. What's inside doesn't change; what calls it doesn't change. No refactor, no bespoke glue for every feature — just one more layer.
Write a flow as a visible chain when you want the topology as data, or as a plain step body when the control flow is genuinely dynamic. ctx.call(step, input) is the one bridge between them, and the audit story is identical under each: everything the model saw is logged and replayable, because the trajectory is enforced below both styles, at the model boundary.
Your logic shouldn't care who serves the tokens. Write a flow once and point it at Anthropic, Bedrock, or a model that runs on your laptop — by changing a string. Develop against free local models, ship on a compliant cloud, fall back to another vendor mid-outage; the code never moves.
Aliases resolve, a provider-neutral effort knob translates per vendor, and supports(capability) lets you degrade gracefully instead of failing at runtime. Every SDK is an optional peer — install only the ones you call.
| PROVIDER | text | tools | schema | streaming | image | reasoning |
|---|---|---|---|---|---|---|
| {{ row.name }} | {{ row.text }} | {{ row.tools }} | {{ row.schema }} | {{ row.streaming }} | {{ row.image }} | {{ row.reasoning }} |
Install, wire a sequence, run it as a value. The docs walk you from a one-liner to a full agentic harness.
Composable TypeScript toolkit for agentic workflows. Compose LLM calls, tools, and plain functions into a Step<i, o>.