Bond¶
The Forensic Runtime for AI Agents
See exactly what your agent is thinking. Watch tool calls form in real-time. Observe every execution and result. Full transparency—nothing hidden.
-
Full-Spectrum Streaming
See every thought, tool call, and result as it happens.
on_thinking_delta,on_tool_call_delta,on_tool_result—nothing is hidden. -
Dynamic Personas
Switch agent personas mid-conversation without creating new instances. The same agent, different cognitive frames.
-
Type-Safe Tools
Built on PydanticAI. All tool inputs and outputs are validated against schemas—no hallucinated arguments.
-
Production Ready
WebSocket, SSE, and print handlers included. Plug Bond into any UI framework with minimal glue code.
Quick Example¶
from bond import BondAgent, StreamHandlers
# Create handlers for transparency
handlers = StreamHandlers(
on_thinking_delta=lambda t: print(f"[Thinking] {t}", end=""),
on_tool_call_delta=lambda name, args: print(f"[Tool] {name}: {args}"),
on_tool_result=lambda id, name, res: print(f"[Result] {name}: {res}"),
on_complete=lambda data: print(f"\n[Done] {data}"),
)
# Create agent with streaming
agent = BondAgent(
name="forensic-assistant",
instructions="You are a helpful assistant. Think step by step.",
model="anthropic:claude-sonnet-4-20250514",
)
# Run with full observability
result = await agent.run(
"What's 2 + 2?",
handlers=handlers,
)
Why Bond?¶
| Feature | Raw API | LangChain | Bond |
|---|---|---|---|
| Streaming | Text only | Callback-based | Full-spectrum events |
| Thinking visibility | Hidden | Partial | Real-time deltas |
| Tool call streaming | After completion | After completion | As it forms |
| Persona switching | New client | New chain | Same instance |
| Type safety | Manual | Optional | Built-in (PydanticAI) |
Bond's philosophy: The agent's reasoning should be as observable as its output.
StreamHandlers: The Forensic Core¶
@dataclass
class StreamHandlers:
# Lifecycle: Block open/close
on_block_start: Callable[[str, int], None] | None = None
on_block_end: Callable[[str, int], None] | None = None
# Content: Incremental deltas
on_text_delta: Callable[[str], None] | None = None
on_thinking_delta: Callable[[str], None] | None = None
on_tool_call_delta: Callable[[str, str], None] | None = None
# Execution: Tool running/results
on_tool_execute: Callable[[str, str, dict], None] | None = None
on_tool_result: Callable[[str, str, str], None] | None = None
# Lifecycle: Response complete
on_complete: Callable[[Any], None] | None = None
Eight callbacks. Complete observability. Zero black boxes.