Robustness — built-in tools, context, approval, resilience, config¶
The features that make YAAB usable out of the box without assembling them yourself.
Built-in tool library¶
A starter toolbox so a new agent is useful immediately:
from yaab import Agent
from yaab.tools.builtin import calculator, current_time, http_get, web_search, python_exec, default_toolset
agent = Agent("a", model="openai/gpt-4o", tools=default_toolset()) # safe read-only set
| Tool | What it does | Notes |
|---|---|---|
calculator |
arithmetic | AST-parsed, never eval |
current_time |
ISO date/time | UTC, optional tz offset |
http_get |
fetch a URL's text | http/https only; lazy httpx |
web_search |
web results | configure a provider via set_search_provider |
python_exec |
run a snippet | isolated subprocess + timeout; gate behind approval |
default_toolset() excludes python_exec (code execution) — opt in explicitly.
Context-window management¶
Stop long conversations from silently overflowing the model window:
from yaab import Agent, TruncateMessages, SummarizeHistory
# Keep system + the most recent N messages:
Agent("a", model="openai/gpt-4o", context_strategy=TruncateMessages(max_messages=20))
# Summarize old history into a running summary once a token budget is hit:
Agent("a", model="openai/gpt-4o", context_strategy=SummarizeHistory(max_tokens=6000, keep_recent=6))
Strategies run before each model call. SummarizeHistory falls back to
truncation if no model is available. Implement ContextStrategy for custom
policies (token-aware, semantic compaction).
Human-in-the-loop tool approval (fast path)¶
The graph engine pauses with interrupt(); for the model-driven loop, require a
human's sign-off on sensitive tools via a plugin:
from yaab import Runner
from yaab.governance import ToolApprovalPlugin
# Inline: await an approver before the tool runs (CLI, Slack bot, queue):
async def approve(tool, args, ctx):
return args.get("amount", 0) < 10_000
runner = Runner(plugins=[ToolApprovalPlugin(tools=["wire_transfer"], approver=approve, audit=gov.audit)])
A rejection short-circuits the tool with a message the model can adapt to. With
no approver, a guarded tool raises ApprovalRequired (carrying the pending
call) so an out-of-band flow can approve and re-run. Guard by tool name or a
needs_approval(tool, args, ctx) predicate. Every decision is audited.
Resilience: rate limiting & circuit breaking¶
Retries/fallbacks live in the model layer; add protection for a failing or rate-limited provider:
from yaab.models.resilient import ResilientModel, RateLimiter, CircuitBreaker
model = ResilientModel(
"openai/gpt-4o", # or any ModelProvider
rate_limiter=RateLimiter(rate=500, per=60), # token bucket
circuit_breaker=CircuitBreaker(threshold=5, cooldown=30),
)
agent = Agent("a", model=model)
The circuit breaker opens after consecutive failures, fails fast for the cooldown, then half-opens to probe recovery.
Declarative agents (YAML)¶
Define an agent as data — an auditable artifact ops and non-coders can review:
# support_bot.yaml
name: support-bot
model: openai/gpt-4o
instructions: You are a helpful support agent.
registry_id: support-bot
max_steps: 8
tools: [calculator, current_time, http_get]
from yaab import agent_from_yaml, agent_from_dict
agent = agent_from_yaml("support_bot.yaml") # path or YAML string
agent = agent_from_dict({...}) # no yaml dependency needed
Unknown tool/skill names fail loudly so typos surface immediately.