ai-agent-handoff
This package is the handoff/protocol component of the
Agentic Security Harness ecosystem.
Its source-owned identity and ordered integration gates are recorded in
component.yaml and the
component roadmap.
Current ecosystem status is extension candidate: the standalone package remains
independently usable, and extensions/harness-v1/ now builds a separately reviewed,
operator-selected extension wheel for Harness API 1. It is not published, automatically
installed, or dependency-resolved. The former
Security Portfolio module contract is preserved as
historical, digest-bound R4 evidence.
A file-based protocol for handing off work between AI coding agents — plus a PreToolUse safety guard that puts deny/ask gates in front of the secret/prod surface.
Multi-agent setups usually pass context by copying chat between agents: lossy, token-expensive, drift-prone. This is the opposite — agents coordinate through three small files and a git-based sync, so a handoff costs one brief, not the whole history.
Distilled from a real Claude + Codex workflow on a long-running project. Templates + an installable, dependency-free guard hook + a worked example. No framework, no lock-in.
Where it fits
This repository is the handoff/protocol layer in the public Agentic AI Security toolchain:
llm-safety-playbooks -> ai-agent-handoff -> agentic-transfer-verifier -> agentic-security-harness
llm-safety-playbooksmakes the human/agent task boundary explicit.ai-agent-handoffturns that boundary into durable files and a reviewable git trail.agentic-transfer-verifierchecks provenance, trust, and authority claims across handoffs.agentic-security-harnessmeasures boundary failures with traces, scorecards, and reports.
The guard is a local seatbelt for known-shaped risky paths and commands. It is not a sandbox and does not claim to make an agent safe by itself.
Portfolio-level documentation authority and public/private storage rules live in the Documentation Contract. This repository owns the handoff protocol and guard; it does not redefine the whole portfolio.
The loop
Agent A writes TASK.md ──► Agent B reads TASK.md (no chat replay)
│
▼
B works in a branch
│
A reads SESSION.md ◄── B appends "↪ Return" to SESSION.md + commits
+ git log / git diff
- A → B: A writes a self-contained
TASK.md(ODAF: Outcome · Data · Action · Format). - B executes: reads the brief — no dialog replay — works in a branch.
- B → A: appends a
↪ Returnblock toSESSION.mdand commits. - A reviews: reads
SESSION.md+git diffand verifies freshness and scope.
Token cost is O(brief), not O(history). The files survive a context reset, but freshness, sequencing, concurrent writers, and repository state still require explicit verification. See docs/protocol.md.
What's inside
- templates/ —
TASK.md(ODAF brief) ·SESSION.md(live state + return channel) ·AGENTS.md(rules + roles) ·ODAF.md(task framing). - src/agent_guard/ — an installable PreToolUse safety guard (deny / ask / allow) for secrets, prod, and dangerous commands. Zero dependencies, tested.
- Handoff metadata sidecar — a strict, bounded digest-and-sequence record that projects to the portfolio observation contract without publishing the Markdown body or granting authority.
- Optional Harness extension — a separate source-owned, dependency-free wheel candidate for explicit Distribution Discovery inspection, approval, lifecycle binding, and advisory content-free observation checks.
- examples/ — a filled-in
TASK.md→SESSION.mdreturn for a real task. - docs/protocol.md — the loop, the diagram, and why it's cheap.
Quickstart (the protocol)
git clone https://github.com/krivonosoff161/ai-agent-handoff
cd ai-agent-handoff
cp templates/AGENTS.md AGENTS.md # your rules + roles (read once per session)
cp templates/SESSION.md SESSION.md # your live state
# for each handoff: write a TASK.md from templates/TASK.md
Tell agent A: "write the next task into TASK.md"; tell agent B: "do TASK.md". No copy-paste between them.
The safety guard
pip install . # provides the `agent-guard` command + the agent_guard package
python -m pytest -q # offline test suite, no network
For contributor work, use pip install -e .[dev]. The wheel intentionally contains the
Python API and agent-guard entry point only. Protocol templates, examples, contracts,
and reviewer documentation are included in the source distribution and repository. CI
builds and inspects both artifacts on Linux and Windows across Python 3.9-3.12; see the
package and CI contract.
The coordinated source candidates are ai-agent-handoff==0.3.0 and
ai-agent-handoff-harness-extension==1.0.0. The nested extension remains dependency-free
and operator-selected. Harness main declares a source-only handoff extra for this
exact pair, but neither candidate is published and the published Harness v1.3.0
metadata does not contain that extra. Public
pip install agentic-security-harness[handoff] support therefore remains unavailable;
exact companion publication and newer Harness package metadata are separate release gates.
from agent_guard import decide
decide({"file_path": "/proj/.env"}) # -> ("ask", "edit to sensitive path ...")
decide({"command": "git push origin main --force"}) # -> ("deny", "forbidden pattern ...")
decide({"file_path": "src/app.py"}) # -> ("allow", "")
Try it from the shell before wiring the hook — the guard answers in Claude Code hook format:
echo '{"tool_input": {"file_path": ".env"}}' | python -m agent_guard
# {"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "ask", ...}}
echo '{"tool_input": {"command": "pytest -q"}}' | python -m agent_guard
# (no output — allow means the guard stays out of the way)
Works the same from bash and PowerShell: the guard reads stdin as UTF-8 and strips a BOM, regardless of console locale.
Wire it as a Claude Code PreToolUse hook in .claude/settings.json:
{ "hooks": { "PreToolUse": [
{ "matcher": "Edit|Write|Bash",
"hooks": [ { "type": "command", "command": "python -m agent_guard" } ] } ] } }
allow = no output (the guard stays out of the way); exit code is always 0. Configure by copying
guard_config.example.json → guard_config.json in your project root
(deny_paths / confirm_paths / deny_command_patterns / confirm_command_patterns).
Defaults protect SSH keys, .pem, .env, secrets/, force-push, rm -rf /, curl | sh, sudo.
Config rules worth knowing:
- Per-key replace, not append — a key in your
guard_config.jsonreplaces that default list entirely; start from the example file to keep the defaults underneath. - Mistakes are loud but never fatal — malformed JSON falls back to defaults, a key with
the wrong type keeps its default, an invalid regex is dropped, an unknown key (a typo like
deny_path) is ignored; every case prints anagent-guard:warning to stderr while stdout stays a clean hook channel and the exit code stays 0. - Matching is deliberately over-eager — path patterns also match as substrings
(
.envflagsx.environment.pytoo). For a guard that's the right direction: a false ask costs one confirmation; a miss costs a secret.
Docs
- Component roadmap — source-owned status and ordered ecosystem integration gates.
- Project map — what's where, guard internals, reviewer checklist.
- Use cases — workflows, what this is not (incl. "not a sandbox"), residual risk.
- Protocol — why files beat chat, the loop.
- Trust boundaries — what the handoff files, git trail, and guard can prove, and where stronger verification starts.
- Metadata sidecar — integrity, sequence, replay and authority limits for machine-readable handoff observations.
- Package and CI contract — source/wheel contents and tested operating-system/Python matrix.
- Optional Harness extension — exact compatibility pins, operator preflight, installed-wheel flow, and non-claims.
What this is not
- Not a security sandbox. The guard pattern-matches known-shaped dangerous calls at one hook point — a seatbelt, not a container. A novel or obfuscated command that matches no pattern passes through. Pair it with real isolation for untrusted work.
- Not an orchestration framework. The protocol is files + git + discipline; there is no runtime to install or operate.
- Not a guarantee. Details and residual risk: docs/use-cases.md.
Why files beat chat
- Cheap: B reads one brief, not the whole conversation; A reads one return +
git diff. - Durable: files remain available after a context reset; they do not prove that the resumed agent loaded the latest revision.
- Shareable: multiple agents can read the same files, but the protocol does not provide locking, ordering, merge, or concurrency guarantees.
- Auditable: everything is
git-versioned; the guard hook is the safety net.
License
MIT — see LICENSE.
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 ai_agent_handoff-0.3.0.tar.gz.
File metadata
- Download URL: ai_agent_handoff-0.3.0.tar.gz
- Upload date:
- Size: 82.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d4ee7a2c7525b386baf52b9bee70128159e3191bcb741a382f11a798a36322b
|
|
| MD5 |
2ff51184e461ee3bd0eb2b251339fe23
|
|
| BLAKE2b-256 |
f3e3fdba04730c9128216d9027482c7bd7cb5e719538d5a95032592790b8e048
|
Provenance
The following attestation bundles were made for ai_agent_handoff-0.3.0.tar.gz:
Publisher:
release-package.yml on krivonosoff161/ai-agent-handoff
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ai_agent_handoff-0.3.0.tar.gz -
Subject digest:
2d4ee7a2c7525b386baf52b9bee70128159e3191bcb741a382f11a798a36322b - Sigstore transparency entry: 2640803974
- Sigstore integration time:
-
Permalink:
krivonosoff161/ai-agent-handoff@bef6edcd5683982d9a8f251ec93974701ed5457a -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/krivonosoff161
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-package.yml@bef6edcd5683982d9a8f251ec93974701ed5457a -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file ai_agent_handoff-0.3.0-py3-none-any.whl.
File metadata
- Download URL: ai_agent_handoff-0.3.0-py3-none-any.whl
- Upload date:
- Size: 17.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc459c07f80406d8a358c0e485ae2896edb64f4ee39c8eac395e83d1a98a46c1
|
|
| MD5 |
0a29bc5c2328648ddc7e69e9aae5bb65
|
|
| BLAKE2b-256 |
9015a2f034c3cd6527a844867af6da85631bfdd014ef0aaf597f673c048d6d3d
|
Provenance
The following attestation bundles were made for ai_agent_handoff-0.3.0-py3-none-any.whl:
Publisher:
release-package.yml on krivonosoff161/ai-agent-handoff
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ai_agent_handoff-0.3.0-py3-none-any.whl -
Subject digest:
fc459c07f80406d8a358c0e485ae2896edb64f4ee39c8eac395e83d1a98a46c1 - Sigstore transparency entry: 2640804033
- Sigstore integration time:
-
Permalink:
krivonosoff161/ai-agent-handoff@bef6edcd5683982d9a8f251ec93974701ed5457a -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/krivonosoff161
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-package.yml@bef6edcd5683982d9a8f251ec93974701ed5457a -
Trigger Event:
workflow_dispatch
-
Statement type: