Agent Tools API Reference¶
The almanak.framework.agent_tools package exposes Almanak's DeFi capabilities as validated, policy-enforced tools that any LLM agent can consume.
from almanak.framework.agent_tools import (
ToolExecutor,
AgentPolicy,
PolicyEngine,
ToolCatalog,
ToolDefinition,
ToolErrorPayload,
ToolResponse,
ToolResponseStatus,
get_default_catalog,
)
ToolExecutor¶
The executor is the bridge between the LLM and the gateway. It validates inputs, enforces policy, dispatches to the gateway, and wraps results in ToolResponse envelopes.
from almanak.framework.agent_tools import AgentPolicy, ToolExecutor, ToolResponseStatus, get_default_catalog
from almanak.framework.gateway_client import GatewayClient, GatewayClientConfig
gateway = GatewayClient(GatewayClientConfig.from_env())
gateway.connect()
executor = ToolExecutor(
gateway,
policy=AgentPolicy(allowed_chains={"arbitrum"}),
catalog=get_default_catalog(),
wallet_address="0x...",
deployment_id="my-agent",
default_chain="arbitrum",
)
# Execute a tool call
result = await executor.execute("get_price", {"token": "ETH", "chain": "arbitrum"})
# result.status == ToolResponseStatus.SUCCESS
# result.data == {"token": "ETH", "price_usd": 1850.0, ...}
Constructor parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
gateway_client |
GatewayClient |
required | Connected gateway instance |
policy |
AgentPolicy |
safe defaults | Safety constraints |
catalog |
ToolCatalog |
built-in | Tool registry |
wallet_address |
str |
"" |
Strategy wallet for balance/execution calls |
deployment_id |
str |
"" |
Deployment ID for state operations |
default_chain |
str |
"arbitrum" |
Default chain when not specified in args |
safe_addresses |
set[str] \| None |
None |
Allowlist of Safe wallet addresses |
AgentPolicy¶
Dataclass defining safety constraints for an agent session. Every field has a safe default.
Spend limits:
| Field | Type | Default | Description |
|---|---|---|---|
max_single_trade_usd |
Decimal |
10000 |
Max USD value per trade |
max_daily_spend_usd |
Decimal |
50000 |
Max cumulative USD per day |
max_position_size_usd |
Decimal |
100000 |
Max position value |
Scope constraints:
| Field | Type | Default | Description |
|---|---|---|---|
allowed_tools |
set[str] \| None |
None (all) |
Allowlist of tool names |
allowed_chains |
set[str] |
{"arbitrum"} |
Allowed blockchains |
allowed_protocols |
set[str] \| None |
None (all) |
Allowed DeFi protocols |
allowed_tokens |
set[str] \| None |
None (all) |
Allowed token symbols |
allowed_intent_types |
set[str] \| None |
None (all) |
Allowed intent types |
allowed_execution_wallets |
set[str] \| None |
None (any) |
Allowed wallet addresses |
Approval gates:
| Field | Type | Default | Description |
|---|---|---|---|
require_human_approval_above_usd |
Decimal |
10000 |
Hard block above this threshold |
require_simulation_before_execution |
bool |
True |
Require dry-run before on-chain |
Rate limits:
| Field | Type | Default | Description |
|---|---|---|---|
max_trades_per_hour |
int |
10 |
Trade rate limit |
max_tool_calls_per_minute |
int |
60 |
Tool call rate limit |
Circuit breakers:
| Field | Type | Default | Description |
|---|---|---|---|
stop_loss_pct |
Decimal |
5.0 |
Portfolio drawdown stop-loss (%) |
max_consecutive_failures |
int |
3 |
Failures before circuit breaker trips |
Economic thresholds:
| Field | Type | Default | Description |
|---|---|---|---|
min_rebalance_benefit_usd |
Decimal |
10 |
Min benefit to justify LP rebalance |
cooldown_seconds |
int |
300 |
Seconds between trades |
require_rebalance_check |
bool |
True |
Require viability check before LP actions |
PolicyEngine¶
Evaluates tool calls against an AgentPolicy. Tracks runtime state (daily spend, trade count, failures).
from almanak.framework.agent_tools import PolicyEngine, AgentPolicy
engine = PolicyEngine(AgentPolicy(max_single_trade_usd=Decimal("100")))
decision = engine.check(tool_def, {"token_in": "USDC", "amount": "50"})
if decision.allowed:
# proceed with execution
...
else:
print(decision.violations) # ["Estimated trade value $500 exceeds..."]
print(decision.suggestions) # ["Reduce amount to at most $100."]
Key methods:
| Method | Description |
|---|---|
check(tool_def, arguments) |
Run all policy checks, return PolicyDecision |
record_trade(usd_amount, success, tool_name) |
Update spend/failure accounting after a trade |
record_tool_call() |
Track tool call for rate limiting |
update_portfolio_value(usd_value) |
Update portfolio value for stop-loss tracking |
reset_daily() |
Reset daily accumulators |
ToolCatalog¶
Registry of all available agent tools.
from almanak.framework.agent_tools import get_default_catalog
catalog = get_default_catalog()
# Look up a specific tool
tool = catalog.get("swap_tokens")
# List all tools
all_tools = catalog.list_tools()
# Filter by category
data_tools = catalog.list_tools(category=ToolCategory.DATA)
# Generate framework-specific schemas
openai_tools = catalog.to_openai_tools()
mcp_tools = catalog.to_mcp_tools()
# Register a custom tool
catalog.register(my_custom_tool)
ToolDefinition¶
Immutable metadata for a single tool.
| Field | Type | Description |
|---|---|---|
name |
str |
Tool name (e.g. "swap_tokens") |
description |
str |
Human-readable description |
category |
ToolCategory |
DATA, PLANNING, ACTION, or STATE |
risk_tier |
RiskTier |
NONE, LOW, MEDIUM, or HIGH |
request_schema |
type[BaseModel] |
Pydantic input model |
response_schema |
type[BaseModel] |
Pydantic output model |
idempotent |
bool |
Whether the tool is safe to retry |
latency_class |
LatencyClass |
FAST (<500ms), MEDIUM (500ms-5s), SLOW (>5s) |
requires_approval_above_usd |
float \| None |
Per-tool approval threshold |
ToolResponse¶
Standard envelope returned by every tool call.
| Field | Type | Description |
|---|---|---|
status |
ToolResponseStatus |
success, simulated, partial, blocked, rejected, or error (lowercase on the JSON wire) |
data |
dict \| None |
Tool-specific result payload |
error |
ToolErrorPayload \| None |
Canonical AgentErrorCode, message, recoverability, and ErrorCategory for error/blocked results |
decision_hints |
dict \| None |
Machine-readable hints for agent reasoning |
explanation |
str \| None |
Human-readable context about the result |
error and blocked statuses require an error payload. Other statuses reject
one. Unknown status values, error codes, fields, and impossible combinations are
rejected at adapter boundaries instead of being forwarded to an agent.
Built-in Tools¶
The default catalog includes 39 tools organized into four categories.
Data Tools (15)¶
Read-only tools with no on-chain side effects. Risk tier: NONE.
| Tool | Description | Key Parameters |
|---|---|---|
get_price |
Get current USD price of a token | token, chain |
get_balance |
Get balance of a single token in a wallet | token, chain, wallet_address |
batch_get_balances |
Get token balances for a wallet on a chain | tokens, chain, wallet_address |
get_indicator |
Calculate technical indicator (RSI, SMA, EMA, MACD, BB, ATR) | token, indicator, period, chain |
get_pool_state |
Get liquidity pool details (price, tick, TVL, fees) | token_a, token_b, fee_tier, chain |
get_lp_position |
Get LP position details (range, liquidity, fees) | position_id, chain |
list_lp_positions |
List all Uniswap V3-style LP positions owned by a wallet (compact per-position summary) | wallet_address, chain |
list_lending_positions |
List a wallet's lending positions with account totals and health factor (Aave V3) | wallet_address, chain |
list_lending_reserves |
List a lending protocol's reserves/markets with borrowable/active/collateral flags. Aave-style reserves enumerate live; market-keyed protocols (morpho_blue) list curated COLLATERAL/LOAN markets with their immutable market_id + LLTV |
protocol, asset, collateral, loan, chain |
get_portfolio |
Aggregate a wallet's on-chain state (native + ERC20 balances, LP positions, lending) | wallet_address, chain |
resolve_token |
Resolve token symbol/address to full metadata | token, chain |
get_risk_metrics |
Get portfolio risk metrics (VaR, Sharpe, vol, drawdown) | chain |
get_vault_state |
Get Lagoon vault state (assets, deposits, share price) | vault_address, chain |
get_wallet_overview |
Complete wallet balance overview in a single call (auto-queries common tokens, filters dust, totals USD) | wallet_address, chain |
check_protocol_support |
Check whether the SDK supports a protocol on a chain (static registry; no network calls) | protocol, chain |
Planning Tools (5)¶
Pre-execution analysis tools. Risk tier: NONE.
| Tool | Description | Key Parameters |
|---|---|---|
compile_intent |
Compile a high-level intent into an ActionBundle | intent_type, chain, token/amount fields |
simulate_intent |
Dry-run an intent without on-chain execution | intent_type, chain, token/amount fields |
validate_risk |
Check an intent against RiskGuard constraints | intent_type, chain, token/amount fields |
estimate_gas |
Estimate gas cost (USD + native token) | intent_type, chain |
compute_rebalance_candidate |
Check economic viability of LP rebalance | position_id, chain |
Action Tools (16)¶
On-chain execution tools. Risk tier: MEDIUM or HIGH. All support dry_run for simulation.
| Tool | Risk | Description | Key Parameters |
|---|---|---|---|
swap_tokens |
MEDIUM | Swap tokens on a DEX | token_in, token_out, amount, chain |
open_lp_position |
HIGH | Open concentrated LP position | token_a, token_b, amount_a, amount_b, price_lower, price_upper |
close_lp_position |
MEDIUM | Close or reduce LP position | position_id, chain |
supply_lending |
MEDIUM | Supply tokens to lending protocol | token, amount, protocol, chain |
borrow_lending |
HIGH | Borrow from lending protocol | token, amount, collateral_token, chain |
repay_lending |
MEDIUM | Repay a lending position | token, amount, chain |
withdraw_lending |
MEDIUM | Withdraw supplied tokens from a lending protocol (full or partial) | token, amount, protocol, chain |
bridge_tokens |
MEDIUM | Bridge tokens cross-chain (Across or Stargate) | token, amount, from_chain, to_chain |
wrap_native |
MEDIUM | Wrap native to ERC-20 (ETH → WETH, MATIC → WMATIC) — required before LP ops when wallet holds native | token, amount, chain |
unwrap_native |
MEDIUM | Unwrap wrapped native back to native (WETH → ETH, WMATIC → MATIC) | token, amount, chain |
execute_compiled_bundle |
HIGH | Execute a previously compiled ActionBundle | bundle_id |
deploy_vault |
HIGH | Deploy a new Lagoon vault | underlying_token, chain |
settle_vault |
MEDIUM | Run vault settlement cycle | vault_address, chain |
approve_vault_underlying |
MEDIUM | Approve vault to pull tokens | vault_address, amount, chain |
deposit_vault |
MEDIUM | Deposit tokens into a vault | vault_address, amount, chain |
teardown_vault |
HIGH | Deterministic vault teardown | vault_address, chain |
State Tools (3)¶
Agent state persistence. Risk tier: LOW or NONE.
| Tool | Risk | Description | Key Parameters |
|---|---|---|---|
save_agent_state |
LOW | Persist agent state across iterations | deployment_id, state |
load_agent_state |
NONE | Load previously saved state | deployment_id |
record_agent_decision |
LOW | Record decision for audit trail | deployment_id, decision_summary |
Error Types¶
All tool errors extend ToolError and include machine-readable codes for agent consumption.
| Error Class | Code | Recoverable | When Triggered |
|---|---|---|---|
ToolValidationError |
validation_error |
Yes | Malformed or missing arguments |
RiskBlockedError |
risk_blocked |
No | Policy or RiskGuard rejection |
SimulationFailedError |
simulation_failed |
Yes | On-chain simulation reverted |
ToolTimeoutError |
timeout |
Yes | Gateway or RPC timeout |
UpstreamUnavailableError |
upstream_unavailable |
Yes | External service unreachable |
PermissionDeniedError |
permission_denied |
No | Action not in allowed set |
ExecutionFailedError |
execution_failed |
No | Transaction reverted on-chain |
Every error includes:
code-- Machine-readable error codemessage-- Human-readable descriptionrecoverable-- Whether the agent should retrysuggestion-- Remediation hint for the agent