Skip to content

Core Concepts

This section explains the fundamental ideas behind AgentHelm.

Tool Contracts

Tools are the building blocks of agent actions. AgentHelm uses a decorator-based approach to define tools with rich metadata:

from agenthelm import tool

@tool(
    requires_approval=True,  # Human-in-the-loop
    max_retries=3,           # Automatic retries
    timeout=30.0,            # Execution timeout
    tags=["financial", "sensitive"]
)
def charge_credit_card(amount: float, card_id: str) -> dict:
    """Charge a credit card for the specified amount."""
    return {"status": "charged", "transaction_id": "txn_123"}

The @tool decorator automatically:

  • Extracts the function signature and docstring
  • Registers the tool in TOOL_REGISTRY
  • Enables execution tracing and cost tracking

Execution Tracing

The ExecutionTracer records every tool call with rich metadata:

from agenthelm import ExecutionTracer
from agenthelm.core.storage import JsonStorage

tracer = ExecutionTracer(storage=JsonStorage("trace.json"))

# Execute a tool with full tracing
output, event = tracer.trace_and_execute(my_tool, arg1="value", arg2=123)

# Event contains: timestamp, inputs, outputs, duration, token_usage, cost, etc.

Event Model

Every execution produces an Event with these fields:

Field Description
timestamp When the event occurred
tool_name Name of the executed tool
inputs / outputs Arguments and return value
execution_duration_ms How long it took
token_usage LLM tokens (input/output/model)
estimated_cost_usd Cost estimate based on pricing
agent_name Which agent executed this
session_id Session identifier
trace_id Unique execution ID

Cost Tracking

AgentHelm includes built-in cost tracking for LLM usage:

from agenthelm import CostTracker, get_cost_tracker

# Token-only tracking (no pricing)
tracker = get_cost_tracker(tokens_only=True)

# Full cost tracking with pricing
tracker = get_cost_tracker()  # Uses built-in pricing.yaml

# Track usage
tracker.record("gpt-4o", input_tokens=500, output_tokens=150)

# Get summary
summary = tracker.get_summary()
# {
#     "total_input_tokens": 500,
#     "total_output_tokens": 150,
#     "total_cost_usd": 0.0055,
#     "by_model": {...}
# }

Approval Handlers

Control human-in-the-loop behavior with different handlers:

from agenthelm import CliHandler, AutoApproveHandler, AutoDenyHandler

# Interactive CLI approval
tracer = ExecutionTracer(approval_handler=CliHandler())

# Auto-approve all (for testing)
tracer = ExecutionTracer(approval_handler=AutoApproveHandler())

# Auto-deny all (for dry-run)
tracer = ExecutionTracer(approval_handler=AutoDenyHandler())

Storage Backends

Events can be stored in different backends:

from agenthelm.core.storage import JsonStorage, SqliteStorage

# JSON file (simple, portable)
storage = JsonStorage("traces.json")

# SQLite (queryable, indexed)
storage = SqliteStorage("traces.db")

# Query by session
events = storage.query(session_id="abc-123", limit=100)

Reliability Features

Retries

@tool(max_retries=3, retry_delay=1.0)
def flaky_api_call(endpoint: str) -> dict:
    """Call an external API that might fail."""
    return requests.get(endpoint).json()

Human Approval

@tool(requires_approval=True)
def delete_file(path: str) -> bool:
    """Delete a file (requires human approval)."""
    os.remove(path)
    return True

Compensating Actions

@tool(compensating_tool="restore_file")
def archive_file(path: str) -> str:
    """Archive a file (can be rolled back)."""
    archive_path = f"{path}.archived"
    shutil.move(path, archive_path)
    return archive_path

@tool()
def restore_file(archive_path: str) -> str:
    """Restore an archived file."""
    original_path = archive_path.replace(".archived", "")
    shutil.move(archive_path, original_path)
    return original_path