TypeScript · Python
One plan. Named steps. Nothing copied by the model.
A model emits a declarative plan of named steps; your application validates and executes it; results flow between steps by name and never travel through the model.
{ "steps": [
{ "id": "drone", "op": "parts.find",
"input": { "filters": [{ "field": "label", "op": "fuzzy", "value": "Aurora Drone" }] } },
{ "id": "components", "op": "parts.components",
"input": { "from": "$drone", "depth": "all" } },
{ "id": "taiwan", "op": "parts.filter",
"input": { "from": "$components",
"filters": [{ "field": "origin", "op": "eq", "value": "Taiwan" }] } }
] }
One tool call, three dependent lookups, zero identifiers copied by the model.
How it works
Define an operation once. Everything else is derived.
The same library, with the same plan format, is published for TypeScript on npm and for Python 3.12+ on PyPI.
You define operations
A name, a description for the model, an input schema, an output type and a handler. Standard operations per collection come for nothing: filter, count, countBy, distinct, mostCommon, first, pick, details.
The model writes a plan
Named steps over your operations. A later step refers to an earlier result as $stepId or $stepId[2]; positions always index the full set, not the preview the model was shown.
Your application runs it
If a plan has any issue, no step runs, and the model reads every issue at once. Independent reads run together, a write runs on its own in the order it was written, a failed step skips only its dependents, and every step is traced.
Packages
Five packages, released together under one version.
On npm as weftai and @weftai/*, and on PyPI as weftai with matching extras. Release tags and each package's changelog are in the repository.
Core runtime
Operations, plans, validation, execution, the result store, the formatter and traces.
Wire-format adapters
OpenAI, Anthropic, Gemini, Bedrock, Ollama and more, so a plan tool reads the same to each.
MCP server
Expose a runtime as an MCP server.
Testing
A test runtime, matchers and fixture helpers.
Command line
weftai run | validate | describe | trace | mcp | init: run saved plans against fixtures with no model in the loop.
Python
The same library and plan format for Python 3.12+, on PyPI.
Run it
One install, in either language.
The README walks through a bill-of-materials example end to end: the operations, the plan a model writes, and the text the model reads back.
- TypeScript, on Node 22.12 or newer.
npm install weftai - Python 3.12 or newer.
pip install weftai
Start with concepts, then writing operations.
Rules it keeps
Rules that are part of the product.
Does my data travel through the model?
No. Results flow between steps by reference and stay in a session-scoped store. The model reads a formatted, token-budgeted view with exact counts, and refers to the full set by name.
What happens when the model asks a wrong question?
It is an error, never an empty result. An unknown field lists the available fields, an unknown step suggests the nearest id, and a reference written into a field that does not take one is refused before anything runs.
Is it tied to one model provider?
No. The plan tool is described once and adapted to each provider's wire format. A model that cannot call tools is an error naming the fix, and an unknown model name is not assumed to speak Chat Completions.
Does it force the model to call it?
No. No adapter sets a forced tool choice by default; the newest OpenAI, Anthropic and Gemini models reject one.
Docs
Written for the person who has to run it.
Concepts
Operations, plans, references and the result store.
The plan format
The JSON a model writes, and every validation issue.
Writing operations
Schemas, outputs, effects and handlers.
Providers
The wire formats it adapts to.
Formatting
What the model reads, and how it is budgeted.
The CLI
Running, validating and tracing plans from a terminal.