Skip to content

Migrating to SDK 0.6

SDK 0.6 is a surgical break — no back-compat with 0.5.x callers or pre-0.6.0 servers. Upgrade both.

The SDK requires tappass server ≥ 0.6.0. Older servers are refused at client construction.

# 0.5: works against any server
Agent("http://tappass", api_key="tp_x")
# 0.6: probes /health; raises TapPassConfigError if server < 0.6.0
Agent("http://tappass", api_key="tp_x")

Upgrade the server first.

ChatResponse now has five required fields populated by the server.

# 0.5: response only has content, pipeline, usage
r = agent.chat("...")
# 0.6: correlation IDs always present
r = agent.chat("...")
r.session_id, r.task_id, r.agent_uuid, r.pipeline_uuid, r.audit_url

If you were defensively accessing these via .get(), simplify — they’re guaranteed.

# 0.5: mutated crew in place
from tappass.integrations.crewai import guard_crew
guarded = guard_crew(crew, constraints={...}, tappass_url=..., api_key="tp_x")
result = guarded.kickoff() # caller drives the crew
# 0.6: context manager; session open/close is explicit
from tappass.integrations.crewai import guard_crew
with guard_crew(crew, tappass_url=..., api_key="tp_x",
constraints={...}) as session:
result = session.kickoff()
print(session.id, session.audit_url)

Calling guard_crew(crew, ...) without with now raises TypeError. No shim.

# 0.5: guard_tools only
tools = guard_tools(tools, tappass_url=..., api_key="tp_x")
# 0.6: high-level guard_agent for whole executor; guard_tools still
# available for the low-level case.
with guard_agent(executor, tappass_url=..., api_key="tp_x") as session:
result = session.invoke({"input": "..."})

OpenAI, Google ADK, MCP, Temporal, A2A, FastAPI

Section titled “OpenAI, Google ADK, MCP, Temporal, A2A, FastAPI”

Each follows the same pattern. See the runtime-governance reference for the full matrix.

PolicyBlockError stayed, but it’s now part of a richer tree. The server can return six different decisions:

from tappass import (
GovernanceDecision,
PolicyBlockError,
RedactionApplied,
ApprovalRequired,
TrustTierDenied,
BreakGlassActive,
ToolIntegrityViolation,
)
try:
r = agent.chat(prompt)
except PolicyBlockError as e:
... # hard block — treat as failure
except ApprovalRequired as e:
print(e.approval_url) # pause, resume via dashboard
except TrustTierDenied as e:
... # agent clearance too low
except GovernanceDecision as e:
... # any other decision

If you previously caught Exception or relied on HTTP response codes, rewire to these subclasses.

The TapPass client no longer has pipelines, create_pipeline, assign, audit, etc. Those moved to the dashboard.

0.5
tp.create_pipeline("strict", steps={...})
tp.assign("my-agent", "strict")
events = tp.audit(agent_id="my-agent")
# 0.6 — removed. Use the web dashboard.
tp.health() # still here
tp.agent(agent_uuid) # still here (lookup)
tp.register_agent("svc", ...) # still here (self-registration on startup)

Callers building custom integrations against the reporter need to enqueue AuditEvent instances instead of raw dicts.

0.5
get_reporter().enqueue(url, key, {"tool": "search", "duration_ms": 12})
# 0.6
from tappass.types import AuditEvent
from datetime import datetime, timezone
get_reporter().enqueue(url, key, AuditEvent(
event_type="tool_call",
session_id="", task_id=None, agent_uuid="",
pipeline_uuid=None,
timestamp=datetime.now(tz=timezone.utc),
payload={"tool": "search", "duration_ms": 12, "outcome": "ok"},
))

Empty session_id/agent_uuid are filled from the active session.