Consistency receipts for multi-agent workflows: state snapshots, handoff packets, outcome checks, and run diffs.
Project description
agent-consistency
Prevent stale-state, broken-handoff, and false-success bugs in multi-agent workflows.
agent-consistency is a small Python library for recording consistency receipts across agent
workflow steps. It is not an agent framework, policy engine, or tracing dashboard. It focuses on a
specific production problem:
Your agents may be smart, but are they acting on the same version of reality?
Multi-agent systems often fail quietly because an agent reads stale state, receives an incomplete
handoff, retries a side effect, or declares success after a tool returned 200 even though the
business outcome is still not true. This library gives each step an explicit receipt:
- what state was read
- what assumptions were made
- what state changed
- what was handed off
- what postcondition proved success
The core package is generic. Azure Durable Functions is the first adapter because replay, resume, and orchestration history make these consistency problems especially visible.
What Is New In 0.2
Version 0.2.0 adds causal consistency features for more realistic agent
systems:
HandoffContractfor declared inputs, evidence, produced artifacts, and verifier namesProofArtifactfor verified outputs such as provider reads, decisions, approvals, files, or ticketsVerifierRegistryfor dynamic verifier selection without hard-coding every check inlineconsume_handoffso downstream agents can reject stale, incomplete, or unverified workbuild_causality_graphandtrace_causalityto explain which upstream step a downstream action relied on
The goal is to make “done” mean more than “the last agent stopped talking.”
Install
From a local checkout:
python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -e ".[dev]"
After publishing:
python -m pip install agent-consistency
Quickstart
from agent_consistency import WorkflowRun
run = WorkflowRun("refund-ord-1")
with run.step("history-agent", "load_order", step_id="history") as step:
order = {"id": "ord_1", "previous_refund_count": 0, "total": 42.5}
order_snapshot = step.read_state("order", order, version="order-v3")
handoff = step.handoff(
to_agent="eligibility-agent",
task="decide refund eligibility",
facts={"order": order, "policy_version": "policy-v12"},
evidence={"order.previous_refund_count": order_snapshot.to_dict()},
required_facts=["order.id", "order.previous_refund_count", "policy_version"],
required_evidence=["order.previous_refund_count"],
)
with run.step("eligibility-agent", "decide", step_id="eligibility") as step:
policy = {"max_previous_refunds": 0, "max_amount": 100}
policy_snapshot = step.read_state("refund_policy", policy, version="policy-v12")
step.ensure_fresh(policy_snapshot, current_version="policy-v12")
step.require_supported_claims(
handoff,
{"eligible": True},
by=["order.previous_refund_count"],
)
with run.step("refund-agent", "issue_refund", step_id="refund") as step:
provider_result = {"refund_id": "rf_1", "status": "settled"}
step.write_state("refund", provider_result, version="refund-rf_1")
step.verify_outcome(
"refund_settled",
lambda: provider_result["status"] == "settled",
details={"refund_id": "rf_1"},
)
for receipt in run.receipts():
print(receipt.to_dict())
Core Features
State Snapshot Guard
Record the exact version and stable hash of state read by an agent step. Before a write, verify the step is still based on fresh state.
from agent_consistency import WorkflowRun
run = WorkflowRun("policy-run")
with run.step("eligibility-agent", "decide") as step:
snapshot = step.read_state("refund_policy", {"limit": 100}, version="v12")
step.write_state(
"refund_decision",
{"eligible": True},
based_on=snapshot,
current_version="v12",
)
By default, consistency violations raise exceptions. You can also use on_violation="warn" or
on_violation="record".
run = WorkflowRun("policy-run", on_violation="record")
Handoff Packet Validator
Make agent-to-agent handoff explicit. Required fields can use dot paths.
packet = step.handoff(
to_agent="refund-agent",
task="issue refund",
facts={"order": {"id": "ord_1", "previous_refund_count": 0}},
assumptions=["order data came from the primary store"],
constraints=["do not refund if the customer was already refunded"],
required_facts=["order.id", "order.previous_refund_count"],
)
Handoff Contracts And Proof Artifacts
Use contracts when a downstream agent should only trust work that declares its inputs, proof artifacts, and verifier.
from agent_consistency import HandoffContract, WorkflowRun
contract = HandoffContract.define(
"refund_approval",
required_facts=["order_id", "amount"],
produced_artifacts=["policy_decision"],
verifier="refund_approval_check",
)
run = WorkflowRun("refund-ord-1")
with run.step("policy-agent", "approve", step_id="policy") as step:
artifact = step.proof_artifact(
"policy_decision",
{"eligible": True, "policy_version": "policy-v12"},
kind="decision",
verified=True,
verifier="policy_rule",
)
packet = step.handoff(
to_agent="refund-agent",
task="issue refund",
facts={"order_id": "ord_1", "amount": 42.5},
artifacts=[artifact],
contract=contract,
)
with run.step("refund-agent", "issue", step_id="refund") as step:
step.consume_handoff(packet, contract=contract)
Outcome Verifier
A tool call is not complete just because it returned. Add a postcondition that proves the business outcome became true.
step.verify_outcome(
"refund_settled",
lambda: payment_provider.get_refund("rf_1")["status"] == "settled",
)
Dynamic Verifier Registry
Dynamic verification means the verification strategy can depend on action, contract, risk, or data. It does not require an LLM.
from agent_consistency import VerifierRegistry
registry = VerifierRegistry()
@registry.register("refund_amount_check")
def refund_amount_check(context):
return context.facts["amount"] < 500
with run.step("refund-agent", "issue", step_id="refund") as step:
step.consume_handoff(packet, contract=contract, registry=registry)
Run Diff
Compare two runs and see where state, assumptions, handoffs, deltas, or outcomes diverged.
from agent_consistency import diff_runs
diff = diff_runs(previous_run_receipts, current_run_receipts)
print(diff.summary())
Causality Trace
Build a small graph of which receipts produced the handoffs and artifacts that later receipts consumed.
from agent_consistency import trace_causality
print(trace_causality(run.receipts()))
Azure Durable Functions Adapter
The Azure Durable adapter has no hard Azure dependency. It works with a Durable orchestration context-like object and provides:
- Durable instance id as the consistency run id
- replay-safe logging helper
- deterministic activity keys for idempotent side effects
- optional custom status updates with receipt summaries
from agent_consistency.adapters import DurableConsistencyContext, replay_safe_log
def orchestrator_function(context):
durable = DurableConsistencyContext(context)
with durable.step("refund-orchestrator", "schedule_refund", step_id="schedule") as step:
intent = {"order_id": "ord_1", "amount": 42.5}
activity_key = durable.activity_key("issue_refund", intent)
step.read_state("refund_intent", intent, version=activity_key)
durable.set_custom_status()
Status
This is an early library with a stable core direction:
- generic consistency receipts
- Azure Durable Functions as the first adapter
- framework adapters later
The goal is to catch quietly wrong success before it becomes production damage.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agent_consistency-0.2.0.tar.gz.
File metadata
- Download URL: agent_consistency-0.2.0.tar.gz
- Upload date:
- Size: 23.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8597fe31db7221deb32d9d69b0fbf8d14e15c04e2c4aeeafb7557aa876180c8e
|
|
| MD5 |
865c2a245c3563d2eb7156e3c7d0be1e
|
|
| BLAKE2b-256 |
bf6a86f5b704e79efe4d7707408713efcc9e4991765f759f0c5bb80e38b57e1b
|
File details
Details for the file agent_consistency-0.2.0-py3-none-any.whl.
File metadata
- Download URL: agent_consistency-0.2.0-py3-none-any.whl
- Upload date:
- Size: 25.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9623168e125d587d1d23db1ab0c47098436f0da1cbd329d2269dc946050c083e
|
|
| MD5 |
64f1b4c786285b8a6a1ac4535c8f4918
|
|
| BLAKE2b-256 |
3cf33adf2d1a3a0ba0863a615dd4c2cdcebef06e3760a5ab32d6a8c754b5141a
|