Examples
See the protocol from each side of the boundary.
These examples show how CHP appears to host implementers, agent frameworks, application teams, and infrastructure providers.
Host
Register and invoke a capability.
Start with one stable capability ID, invoke through the host, and replay the evidence by correlation ID.
from chp_core import LocalCapabilityHost, capability
host = LocalCapabilityHost("my-host")
@capability(id="payments.transfer", version="1.0.0", description="Transfer funds.")
def transfer(amount: float, to: str):
execute_transfer(amount, to)
return {"status": "ok", "amount": amount}
host.register(transfer)
result = host.invoke(
"payments.transfer",
{"amount": 100.0, "to": "acct_456"},
correlation_id="session-abc",
)
events = host.replay("session-abc")
# → execution_started, execution_completedAgent
Capture tool calls as evidence.
Agent CLIs can route tool calls through CHP hooks without changing application code.
# One command — no application code changes required
chp hooks install
# → Hooks registered for Claude Code
# → Every tool call intercepted: Bash, Read, Edit, Write, WebFetch...
# → Evidence stored to ~/.chp/evidence.sqlite automatically
# Then inspect any session:
chp session list
chp session tree <session_id>
chp session autonomy-report <session_id>
chp session otel <session_id> --endpoint http://localhost:4318Application
Wrap model calls behind one contract.
Provider adapters make model calls look like governed capabilities with shared evidence fields.
from chp_core import LocalCapabilityHost, register_adapter
from chp_core.adapters import ClaudeAdapter, OpenAIAdapter, GeminiAdapter
host = LocalCapabilityHost("my-agent")
# Same governance layer regardless of provider
register_adapter(host, ClaudeAdapter(api_key=ANTHROPIC_KEY))
register_adapter(host, OpenAIAdapter(api_key=OPENAI_KEY))
register_adapter(host, GeminiAdapter(api_key=GOOGLE_KEY))
# Every LLM call → governed, auditable, replayable
result = host.invoke("claude.messages_create", {
"model": "claude-opus-4-8",
"messages": [{"role": "user", "content": "Summarize this document."}],
"max_tokens": 1024,
})
# Captured automatically: input_tokens, output_tokens, latency_ms, finish_reasonInfrastructure
Publish policy as a trust layer.
Policy files let hosts return structured denials before unsafe invocations execute.
// .chp/policy.json — loaded automatically on host startup
{
"max_risk_tier": "medium",
"audit_only": false,
"block_patterns": [
{ "capability_id": "claude_code.bash", "payload_pattern": "rm -rf" },
{ "capability_id": "claude_code.bash", "payload_pattern": "DROP TABLE" },
{ "capability_id": "*.delete", "payload_pattern": "production" }
],
"allowed_capability_ids": ["payments.*", "retrieval.*", "memory.*"],
"block_capability_ids": ["claude_code.web_fetch"]
}Evidence
Every example should produce replayable evidence.
The output is not just a log line. It is a typed event with capability identity, version, correlation, outcome, timing, and integrity fields.
{
"event_id": "evt_8f3a1c",
"event_type": "execution_completed",
"invocation_id": "inv_session_abc_001",
"capability_id": "payments.transfer",
"capability_version": "1.0.0",
"host_id": "my-host",
"correlation": { "correlation_id": "session-abc" },
"sequence": 2,
"timestamp": "2026-06-03T00:14:22.104Z",
"outcome": "success",
"payload": { "duration_ms": 43 },
"redacted": true,
"assurance": { "level": "S1" }
}Add safety before broad exposure.
Denials should be protocol outcomes. Start with explicit safety checks before capabilities become available to independent callers.
evaluator = RuleBasedSafetyEvaluator(max_risk_tier="medium")
register_safety_capability(host, evaluator)
# Invocations above "medium" risk emit execution_denied — not an exception
result = host.invoke("finance.wire_transfer", payload)
if not result.success:
print(result.denial.code) # → "risk_tier_exceeded"