A lightweight Python framework for building multi-agent workflows with structured state transfer protocols.
Project description
HandoffKit
Structured state transfer for multi-agent Python workflows.
Build agent chains where each agent receives a clear contract: task, decisions, files, errors, next steps, and metadata. No messy context soup.
pip install handoffkit
What It Is
HandoffKit is a lightweight Python framework for building multi-agent AI workflows where agents pass structured state instead of free-text summaries.
Most multi-agent demos do this:
Agent A -> "Here is roughly what happened..." -> Agent B
HandoffKit does this:
Architect
task: "Build a calculator CLI"
decisions: ["Use argparse", "Keep operations pure"]
files: ["calculator.py", "test_calculator.py"]
next_steps: ["Implement CLI", "Run pytest"]
|
v
Coder
receives HandoffState, not a vague paragraph
|
v
Tester
receives decisions, files, errors, and test evidence
That makes agent workflows easier to inspect, test, replay, and improve.
What 0.3.0 Adds
HandoffKit 0.3.0 adds a real tool execution loop:
ToolCallandToolResultmodels,ToolRegistryfor registering and executing tools by name,Agent.run_with_tools()for structured tool loops,- deterministic local tool execution with
EchoProvider, - provider JSON tool-call mode for fake or real providers,
- basic safety checks for shell and write operations,
ToolExecutionReportwith JSON and Markdown export.
Why HandoffKit?
Multi-agent systems break when context handoffs are vague. One agent makes a decision, another agent never sees it. One agent finds an error, the next agent gets only a polished summary. Files, constraints, and validation evidence vanish.
HandoffKit gives you:
Agent: a small role-based agent abstraction.HandoffState: a JSON-friendly contract between agents.HandoffProtocol: protocol modes for different transfer styles.Team: sequential multi-agent execution.tool: typed Python tools with schema metadata.EchoProvider: deterministic local provider for tests and demos.OllamaProvider: local Ollama integration.OpenAIProvider: OpenAI and OpenAI-compatible APIs.
Core Concept
from handoffkit import Agent, HandoffProtocol
architect = Agent("Architect", "Create implementation plans.")
coder = Agent("Coder", "Implement from structured handoff state.")
protocol = HandoffProtocol(mode="hybrid_state")
state = protocol.transfer(
from_agent=architect,
to_agent=coder,
task="Create a small Python CLI calculator with tests.",
summary="Build a dependency-free CLI with pytest coverage.",
decisions=["Use argparse.", "Keep calculator operations pure."],
important_files=["calculator.py", "test_calculator.py"],
next_steps=["Implement code.", "Run pytest."],
)
state.validate()
print(state.to_json())
Protocols
| Mode | What it passes | Best for |
|---|---|---|
natural |
Human-readable summary | Simple demos and debugging |
compressed |
Compact summary | Token-sensitive transfers |
hybrid_min |
Task, summary, next steps | Lightweight structured chains |
hybrid_state |
Full state contract | Replayable, testable workflows |
Quickstart
from handoffkit import Agent
agent = Agent(
name="Planner",
role="Create concise implementation plans.",
)
print(agent.run("Create a plan for a Python CLI app with tests."))
No API key required. By default, HandoffKit uses EchoProvider, so examples and
tests run locally and deterministically.
Tool Schema Example
from handoffkit import tool
@tool
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
print(add.to_schema())
print(add.run(a=2, b=3))
Output:
{
"name": "add",
"description": "Add two numbers.",
"parameters": {
"type": "object",
"properties": {
"a": {"type": "integer"},
"b": {"type": "integer"},
},
"required": ["a", "b"],
},
}
Tool Execution Loop
Register Python tools, let an agent create structured ToolCall objects, execute
them through a ToolRegistry, and receive structured ToolResult objects.
from handoffkit import Agent
from handoffkit.tools.filesystem import list_files, read_file
agent = Agent(
name="FileAgent",
role="Use tools to inspect files.",
tools=[read_file, list_files],
)
result = agent.run_with_tools("read file README.md")
print(result.final_output)
print(result.tool_results)
There are two modes:
- Deterministic/local mode: with
EchoProvider, HandoffKit handles simple tasks such asread file README.md,list files .,write file ..., orrun command .... This is honest local automation, not hidden AI reasoning. - Provider JSON mode: if a provider returns JSON with
tool_calls, HandoffKit executes those tools and feeds results into the next step until the provider returns{"final": "..."}ormax_stepsis reached.
Provider tool-call JSON:
{
"tool_calls": [
{
"tool_name": "read_file",
"arguments": {
"path": "README.md"
}
}
],
"final": null
}
Safety:
- dangerous shell commands such as
rm -rf,del /s,format,shutdown,reboot,mkfs, anddiskpartare blocked; - when
require_approval=True, write and shell tools returnapproval_requiredinstead of executing.
Real Task Demo
HandoffKit includes a reproducible real task demo:
python examples/real_task_calculator.py
It runs this workflow:
Architect -> Coder -> Tester -> Reporter
Task:
Create a tiny Python CLI calculator with add, subtract, multiply and divide
operations, plus tests.
The demo creates a real generated project:
examples/output/calculator_cli/
calculator.py
test_calculator.py
README.md
It also writes reproducibility reports:
reports/real_task_calculator.md
reports/real_task_calculator.json
The generated project is tested with pytest, and the report captures command,
cwd, return code, stdout, stderr, files created, provider used, model used, and
handoff flow.
Providers
Local deterministic provider
from handoffkit import Agent
agent = Agent("Planner", "Plan work.")
print(agent.run("Prepare a package release."))
Ollama
ollama pull llama3.1
ollama serve
python examples/ollama_agent.py --model llama3.1
OpenAI-compatible APIs
$env:OPENAI_API_KEY="..."
$env:OPENAI_BASE_URL="https://api.freemodel.dev/v1"
$env:OPENAI_MODEL="gpt-4o-mini"
python examples/freemodel_openai_compatible.py
Optional real API tests are skipped unless explicitly enabled:
$env:HANDOFFKIT_RUN_API_TESTS="1"
$env:OPENAI_API_KEY="..."
$env:OPENAI_BASE_URL="https://api.freemodel.dev/v1"
$env:OPENAI_MODEL="gpt-4o-mini"
pytest tests_api -q
Use temporary or scoped provider tokens. Do not commit API keys.
CLI
handoffkit --version
handoffkit demo
Examples
python examples/simple_agent.py
python examples/handoff_demo.py
python examples/coding_team.py
python examples/tool_schema_demo.py
python examples/tool_execution_demo.py
python examples/fake_provider_tool_call_demo.py
python examples/real_task_calculator.py
Development
git clone https://github.com/DaosPath/handoffkit.git
cd handoffkit
pip install -e ".[dev]"
Run checks:
ruff check .
pytest -q
python -m build
python -m twine check dist/*
Publishing
Build and validate:
python -m build
python -m twine check dist/*
Upload to TestPyPI first:
python -m twine upload --repository testpypi dist/*
Upload to PyPI only after TestPyPI install verification:
python -m twine upload dist/*
Inspiration
HandoffKit is inspired by the research and reproducibility repository
DaosPath/state-transfer-protocols,
especially its comparison of natural, compressed, hybrid_min, and
hybrid_state handoff protocols for multi-agent workflows.
HandoffKit is a developer library, not a copy of that repository.
Roadmap
- richer contract validators,
- broader tool schema coverage,
- provider adapters,
- structured tool calling loops,
- handoff quality metrics,
- memory integrations,
- benchmark-inspired examples,
- multi-agent workflow templates.
License
MIT.
Project details
Release history Release notifications | RSS feed
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 handoffkit-0.3.0.tar.gz.
File metadata
- Download URL: handoffkit-0.3.0.tar.gz
- Upload date:
- Size: 39.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2e9c160bc0610f8e16aa83d9d9ccb546e6e1943447f1d3f4a9d71325ae2534d
|
|
| MD5 |
a9315d031b25ec634316ed93f0726280
|
|
| BLAKE2b-256 |
0d60fd01e349c0a8444e2bdc1376479a5607126e2afe3b99df00228cacd3c846
|
File details
Details for the file handoffkit-0.3.0-py3-none-any.whl.
File metadata
- Download URL: handoffkit-0.3.0-py3-none-any.whl
- Upload date:
- Size: 29.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b23efd8916e811d197dae8a25513e0d1e4a2a022cbd26d8dd26384943730679b
|
|
| MD5 |
4965290306c2d0000c80984864a538f6
|
|
| BLAKE2b-256 |
956c9335fd7c4f784e9a07826c71e2b1c69c7672403f5204e97fc4ffce589471
|