Skip to content

Tool Step

ToolStepDescription executes a Python function you registered on the context. Its behaviour is configured with ToolStepConfig.

Tools are looked up by name in the context’s tool registry:

def calculate_growth(data: str) -> dict:
return {"growth_rate": 0.15, "trend": "positive"}
context.register_tool("calculate_growth", calculate_growth)
FieldTypeDefaultPurpose
tool_namestr— (required)Name of the registered tool.
tool_descriptionstr""What the tool does.
parameterslist[ToolParameter][]Declared input parameters.
input_mappingdict[str, str]{}Maps tool parameter names → context references (e.g. "$history[-1]").
output_keystr"result"Key under which the output is stored in the step result.
timeoutfloat30.0Execution timeout in seconds.
retry_on_errorboolTrueWhether to retry on error.
error_recoveryToolErrorRecovery | NoneNoneRetry + fallback strategy (below).
allowed_tool_tagslist[str] | NoneNoneWhitelist of tags; the executor refuses tools whose tags don’t intersect.
from mmar_carl import ToolStepDescription, ToolStepConfig
ToolStepDescription(
number=2,
title="Calculate growth",
dependencies=[1],
config=ToolStepConfig(
tool_name="calculate_growth",
input_mapping={"data": "$history[-1]"}, # feed step 1's output
),
)

ToolErrorRecovery adds retries and fallback tools:

FieldTypeDefaultPurpose
retry_maxint0Extra attempts after the first failure.
retry_delayfloat0.0Seconds between attempts.
on_timeoutstr | NoneNoneFallback tool name to call on timeout.
on_exceptionstr | NoneNoneFallback tool name to call after retries are exhausted.
from mmar_carl import ToolStepConfig, ToolErrorRecovery
ToolStepConfig(
tool_name="web_search",
error_recovery=ToolErrorRecovery(
retry_max=2,
retry_delay=1.0,
on_timeout="cached_search", # registered fallback tool
on_exception="cached_search",
),
)

The fallback tool receives the same keyword arguments as the primary tool.

Use the @carl_tool decorator + dynamic discovery to register tools in bulk (from a module, a glob, or a factory) instead of one register_tool call at a time.