Compose LLM calls, tools, and plain functions into a Step<i, o>. Wire eighteen primitives together over one generate surface. 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.
Anthropic, OpenAI, Bedrock, Google, OpenRouter — or a local model on your laptop — all sit behind one generate. Swap providers by changing a string, not your code.
No decorators, no dependency injection, no ambient scheduler deciding when your code runs. A flow is plain functions you can read top to bottom, set a breakpoint in, and unit-test.
A toolkit, not a framework. Fascicle never dictates your app's shape — drop a Step into the code you already have. No rewrite, no buy-in, no ORM telling you how to build.
Every primitive takes a Step<i,o> and returns a Step<i,o>. Wrap one in retry, fallback, or ensemble 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.
model_call turns a provider into a Step<i, o> — so every primitive you've already seen applies to it. Wrap it in retry, fan it out with map, race it with fallback. There's no second API for “calling a model carefully.”
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. There's no privileged “top level,” no interface that 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.
Your logic shouldn't care who serves the tokens. Write a flow once and point it at Anthropic, Bedrock, or a model running 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>.