Fleetwrit Python SDK
The independent authorisation record for consequential AI-agent actions.
An agent stops before a consequential action, a named human decides, and the agent resumes on exactly that decision with a signed receipt — a record that is tamper-evident and lives outside the system being governed.
This is fleetwrit-python, the SDK. The server and dashboard live in the
separate fleetwrit repository. This
is an alpha: the SDK surface, the fingerprint, action definitions, the policy
hook, the testing helpers and the CLI are implemented and tested, the live HTTP
transport works against the Fleetwrit server, and the LangGraph, OpenAI
Agents, and Bedrock AgentCore integrations are real and covered by tests.
The LlamaIndex adapter and the OPA/Cedar policy engines are still stubs marked "coming in a
later gate".
Install
pip install fleetwrit
Extras pull in framework integrations and policy engines:
pip install "fleetwrit[langchain]" # or [llamaindex], [openai-agents], [agentcore]
pip install "fleetwrit[opa]" # or [cedar]
pip install "fleetwrit[dev]" # pytest, hypothesis, jsonschema
Run the local stack
The dev-server extra pulls in the local server with the dashboard bundled in,
so one install and one command bring up the whole thing — no repo checkout, no
Docker, no Node:
pip install "fleetwrit[dev-server]"
fleetwrit dev # server API + dashboard on http://localhost:4100
It starts empty — set FLEETWRIT_URL=http://localhost:4100 in your agent and
develop against it. It auto-picks a free port if 4100 is taken.
Flags: --port, --no-dashboard, --demo (load sample data), --dashboard-port.
The three calls and a guard
import fleetwrit
from fleetwrit import action, Money
@action(
type="refund.issue",
title="Issue refund",
risk="high",
reversible=False,
queue="finance-ops",
summary="Refund {amount} to customer on charge {charge}",
display={"amount": Money(currency_field="currency")},
editable=["amount"],
)
def issue_refund(charge: str, amount: int, currency: str) -> str:
... # your Stripe call
fw = fleetwrit.Client() # reads FLEETWRIT_URL, FLEETWRIT_API_KEY, ...
decision = fw.approve(
issue_refund.action(charge="ch_123", amount=400000, currency="gbp"),
context={"ticket": "ZD-99120"},
)
if decision.approved:
with decision.authorize(): # passes only for the approved action
issue_refund(**decision.action.args)
else:
print(decision.reason)
| Call | Use |
|---|---|
approve(action, ...) |
Yes / yes-with-edits / no on one exact action |
input(prompt, schema=...) |
A fact only a human has |
choose(prompt, options) |
Pick one of 2–6 candidate actions |
decision.authorize() |
Context manager; blocks if the action no longer matches |
fw.task(name) |
Counts agent tasks (the north-star denominator) |
fw.guard(policy=...) |
Ask a policy engine first, a human only if told to |
Configuration
FLEETWRIT_URL, FLEETWRIT_API_KEY, FLEETWRIT_AGENT_ID,
FLEETWRIT_ENVIRONMENT. Keys are scoped to one agent and one environment.
Testing your agent offline
fleetwrit.testing runs an in-memory fake server so you can test approval
paths with no network and no reviewer:
from fleetwrit import testing
fw = testing.client(testing.auto_approve())
decision = fw.approve(issue_refund.action(charge="ch_1", amount=500, currency="gbp"))
assert decision.approved
# also: testing.auto_reject("nope"), testing.scripted([...])
# and the `fleetwrit_client` pytest fixture
Run the bundled examples offline:
python examples/refund_agent.py
python examples/sre_agent.py
How the fingerprint works
The fingerprint is sha256: over the canonical JSON (sorted keys, compact
separators, UTF-8) of type, version, tool, args, agent_id and
environment. The SDK computes it and the server recomputes it. The
idempotency key is sha256(run_id|step_id|fingerprint).
The v0 canonicaliser is an approximation of RFC 8785 (JCS): it agrees for strings, keys, booleans, null and integers, but does not implement JCS ECMAScript number formatting for exotic floats. Conformance vectors in
protocol/vectors/fingerprint.jsonpin the expected bytes for other implementations to reproduce.
Policy engines
from fleetwrit.policy import OPA, Verdict, Policy
guard = fw.guard(policy=OPA(url="http://opa:8181", path="agents/actions/verdict"))
guard.run(issue_refund, charge="ch_123", amount=400000, currency="gbp")
A policy returns a Verdict of allow, deny or ask. allow executes,
deny raises PolicyDenied, ask calls approve and then executes the
approved action. OPA and Cedar are stubs in v0; implement Policy.evaluate
for a custom engine.
CLI
fleetwrit dev # would start the local server (stub)
fleetwrit actions lint # lint @action definitions (stub)
fleetwrit ledger verify # verify the ledger chain (stub)
fleetwrit report # usage report (stub)
Development
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest
nox runs the suite across Python 3.10–3.13, the examples, and the
no-framework import check.
Releasing to PyPI
Publishing is automated by .github/workflows/publish.yml, which runs on a
published GitHub Release and uploads via PyPI Trusted Publishing (OIDC — no
API token is stored in the repo). One-time setup on PyPI:
- Register (or reserve) the
fleetwritproject on PyPI. - Add a Trusted Publisher: owner
teopopescu, repofleetwrit-python, workflowpublish.yml, environmentpypi. - Cut a GitHub Release tagged
v<version>(matchingpyproject.toml). The workflow builds the sdist + wheel and publishes them.
To publish with an API token instead, add a PYPI_API_TOKEN secret and pass it
as password: to the publish step.
Licence
Apache-2.0. Contributions use a DCO sign-off, not a CLA.
Release files for fleetwrit 0.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fleetwrit-0.0.2.tar.gz | 33.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fleetwrit-0.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 65.5 kB
Release files / fleetwrit-0.0.2.tar.gz
| Download URL | fleetwrit-0.0.2.tar.gz |
|---|---|
| Size | 33.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1b32c5830dc2d55b6fb098e5e40f1b0a5c4f8ebb299dcc975b84c47e8bd71550
|
|
BLAKE2b-256 checksum How to use checksums |
84e8ad60acc61ef2058d0b6b15332740cbef4f04ba6dfa1ee339a1aea32f1243
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 19, 2026.
Transparency logRelease files / fleetwrit-0.0.2-py3-none-any.whl
| Download URL | fleetwrit-0.0.2-py3-none-any.whl |
|---|---|
| Size | 31.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
72f9b1ec2847ec63361703267bf81eb63340d04f27844b0055edf9ad596597b4
|
|
BLAKE2b-256 checksum How to use checksums |
8a8e86322ee00fdd8452fa2dd78d841bcd13c57f9e57d5b74b3eff894dfe219b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 19, 2026.
Transparency log