Skip to content

agentix.executors

executors

Tool execution — the boundary where tool calls actually run.

The executor is deliberately separate from the model and from tool definitions: the registry says what tools exist, the executor says how (and under what limits) they run. Keeping execution here is what lets you drop in a sandboxed executor later without touching the loop. The loop passes the policy's network_allowlist and timeout_s so those limits can't be influenced by the model.

ToolExecutor

Bases: Protocol

Executes a single tool call under policy-enforced limits.

LocalToolExecutor

LocalToolExecutor(tools: Mapping[str, ToolFn])

Runs tools in-process by dispatching to a mapping of name -> callable.

Callables may be sync or async and are invoked with the tool-call args as keyword arguments. Each call is bounded by timeout_s. This executor does NOT sandbox the network or filesystem and cannot honour network_allowlist (an in-process call can open any socket) — it's the default for trusted, in-process tools. For untrusted tools or model-generated code, use :class:~agentix.sandbox.SubprocessExecutor, which runs each call in an isolated subprocess and enforces the network/resource limits.

Concurrency: synchronous tool functions are run in a worker thread (via :func:asyncio.to_thread) so a blocking tool can't stall the event loop and starve other concurrently-running agents — and so timeout_s can actually return control (a blocking sync call cannot be timed out while it holds the loop). Note: a timed-out sync tool's thread keeps running in the background until it returns — Python can't forcibly kill a thread — and sync tools draw from the default thread-pool, so size that pool for your concurrency (loop.set_default_executor(...)). Async tools run inline.