Skip to main content

weftai

Composable AI workflows. 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.

One tool call answers a question that would otherwise take several, and the model never copies an identifier from one result into the next request.

pip install weftai

Python 3.12 or newer; pure Python, tested on Linux and Windows. The same library is on npm as weftai, with the same plan format and the same model-facing text.

Quick start

Define a collection and the operations that return it, then execute a plan:

import asyncio
from dataclasses import dataclass

from weftai import (
    BaseModel,
    FieldSpec,
    collection,
    create_registry,
    create_runtime,
    define_operation,
    standard_operations,
)
from weftai.schema.spec import object_schema


class Ticket(BaseModel):
    id: str
    title: str
    status: str


Tickets = collection(
    "tickets",
    Ticket,
    label=lambda ticket: ticket.title,
    key=lambda ticket: ticket.id,
    fields=lambda _ctx: [FieldSpec("status", lambda ticket: ticket.status)],
)

find = define_operation(
    {
        "name": "tickets.find",
        "description": "Every ticket. Start here.",
        "input": object_schema({}),
        "output": Tickets,
        "run": lambda run: run.ctx.tickets,
    }
)

runtime = create_runtime(
    {"registry": create_registry({"operations": [find, *standard_operations(Tickets)]})}
)


@dataclass
class Context:
    tickets: list[Ticket]


tickets = [
    Ticket(id="t1", title="Login page times out", status="open"),
    Ticket(id="t2", title="Export drops the last row", status="open"),
    Ticket(id="t3", title="Typo on the pricing page", status="closed"),
]


async def main() -> None:
    result = await runtime.execute(
        {
            "steps": [
                {"id": "all", "op": "tickets.find"},
                {
                    "id": "open",
                    "op": "tickets.filter",
                    "input": {"from": "$all", "filters": [{"field": "status", "value": "open"}]},
                },
            ]
        },
        {"ctx": Context(tickets), "session": {"id": "conversation-1"}},
    )
    print(result["text"])


asyncio.run(main())

result["text"] is what the model reads:

all (tickets): 3 matched
  1. Login page times out
  2. Export drops the last row
  3. Typo on the pricing page
  [intermediate step - preview only; reference $all to use the full set]
open (tickets): 2 matched
  1. Login page times out
  2. Export drops the last row

result["steps"] has each step's status, data, notices and timing, and result["trace"] is JSON for the CLI or an inspector. A later plan in the same session can use $open or $open[2]: results are kept in a session-scoped store, and positions always index the full set.

The plan a model writes

A plan is a list of steps. Each has an id, an operation op, and an input; a string such as "$all" in a field that takes a reference is the result of an earlier step, resolved by the runtime rather than copied by the model:

{ "steps": [
  { "id": "all",  "op": "tickets.find" },
  { "id": "open", "op": "tickets.filter", "input": { "from": "$all", "filters": [{ "field": "status", "value": "open" }] } }
] }

What you get from one definition

  • Validation with actionable errors. An unknown operation suggests the nearest name, an unknown field lists the available ones, and a reference to the wrong kind of result says which kind was expected. A wrong question is an error, never an empty result.
  • Typed references. ref(Tickets) renders as a $stepId string for the model and arrives in the handler as a collection. A whole reference written into a field that does not take one is refused before anything runs.
  • Execution in dependency order. Independent steps run together, a failed step skips only its dependents, and timeouts and cancellation are built in.
  • Token-budgeted formatting that never truncates silently: exact counts, showing 30 of 35, and a notice for every cap that applied.
  • Standard operations for every collection: filter, count, countBy, distinct, mostCommon, first, pick and details.
  • Decisions. A Decider answers short, typed questions (a choice, a score, a yes or no) with probabilities; NullDecider abstains, and weftai-providers has an HTTP one.

Packages

Package Import Purpose
weftai weftai Operations, plans, validation, execution, the result store, formatting and traces
weftai-providers weftai.providers Present a runtime as a tool on OpenAI, Anthropic, Gemini, Bedrock, Ollama, Cohere and more
weftai-mcp weftai.mcp Serve a runtime over the Model Context Protocol
weftai-cli weftai.cli The weftai command: run, validate, describe, trace, mcp and init
weftai-testing weftai.testing A test runtime, assertions and a pytest plugin

pip install "weftai[all]" installs the first four. All five are released together and share a version. The concepts, plan format and formatting rules are described in the weftai guides, written for the npm package; the Python API spells each name in snake_case.

License

MIT

Metadata

Release files for weftai 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for weftai 0.7.0
File Size Uploaded Provenance Actions
weftai-0.7.0.tar.gz 64.0 kB With provenance Details for weftai-0.7.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for weftai 0.7.0
File Interpreter ABI Platform Actions
weftai-0.7.0-py3-none-any.whl Python 3 none any Details for weftai-0.7.0-py3-none-any.whl

Total release size: 151.6 kB

Release files / weftai-0.7.0.tar.gz

Download URL weftai-0.7.0.tar.gz
Size 64.0 kB
Tags Source
SHA-256 checksum
How to use checksums
cb640904402179caa306f343fe0834bf43fbc36cd17d845064a4bd446d882f73
BLAKE2b-256 checksum
How to use checksums
46fe9e379827c22c6de372caa418980c0f4f7198e8efb820137b9a8a5d4a4575
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Release files / weftai-0.7.0-py3-none-any.whl

Download URL weftai-0.7.0-py3-none-any.whl
Size 87.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2b1e1ef80d4eeb367c8cf6b3aa7bff28f079fc0f9adba4082a8b09c481434e81
BLAKE2b-256 checksum
How to use checksums
f41fb61c906029e9c70b52c1fc061294e8615c07c829d7783c46856b54129ad5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Security for weftai 0.7.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for weftai-0.7.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page