Files
cleveragents-core/docs/reference/tool_runtime.md
T
Jeff (CTO) 18482b938f
CI / typecheck (push) Waiting to run
CI / lint (push) Waiting to run
CI / security (push) Waiting to run
CI / quality (push) Waiting to run
CI / unit_tests (push) Waiting to run
CI / integration_tests (push) Waiting to run
CI / coverage (push) Blocked by required conditions
CI / build (push) Waiting to run
CI / docker (push) Blocked by required conditions
CI / lint (pull_request) Successful in 14s
CI / typecheck (pull_request) Successful in 27s
CI / security (pull_request) Successful in 22s
CI / quality (pull_request) Successful in 15s
CI / integration_tests (pull_request) Successful in 4m32s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Successful in 9m45s
CI / coverage (pull_request) Successful in 6m53s
CI / docker (pull_request) Successful in 39s
feat(tool): add tool runtime core
2026-02-14 13:46:10 -05:00

3.3 KiB

Tool Runtime

The tool runtime provides the execution layer that sits on top of the domain Tool model. It is responsible for registering, discovering, activating, executing, and deactivating tools at runtime.

Modules

Module Purpose
cleveragents.tool.runtime Data models: ToolSpec, ToolResult, ToolError
cleveragents.tool.registry In-memory ToolRegistry with thread-safe operations
cleveragents.tool.runner ToolRunner implementing the four-stage lifecycle

Tool Lifecycle

Every tool execution follows a strict four-stage lifecycle:

discover -> activate -> execute -> deactivate

1. Discover

ToolRunner.discover(registry?) queries the registry for all available tools. An alternate registry may be passed for dynamic discovery.

2. Activate

ToolRunner.activate(tool_name) validates that the tool exists and marks it as ready for execution. Raises ToolError with type ActivationError if the tool is not found.

3. Execute

ToolRunner.execute(tool_name, inputs) runs the tool handler with the provided inputs. Key guarantees:

  • JSON-serialisable IO: Both inputs and outputs are validated to be JSON-serialisable. Non-serialisable data causes a ToolResult with success=False.
  • Error normalisation: Any exception raised by the handler is caught and returned as a ToolResult(success=False, error=...). The caller never sees raw exceptions from tool handlers.
  • Duration tracking: Wall-clock execution time is recorded in ToolResult.duration_ms.

4. Deactivate

ToolRunner.deactivate(tool_name) cleans up after execution. Returns True if the tool was active, False otherwise.

Capability Flags

ToolSpec.capabilities carries a ToolCapability instance (from the domain model) with the following flags:

Flag Description
read_only Tool only reads; never writes
writes Tool can write to resources
checkpointable Tool supports checkpoint/rollback
idempotent Safe to re-run without side effects
unsafe Requires extra safety checks
human_approval_required Needs explicit human approval

A read_only tool cannot have writes=True or checkpointable=True.

Error Semantics

ToolResult

Field Type Description
success bool Whether execution succeeded
output dict JSON-serialisable output payload
error str | None Error message on failure
duration_ms float Execution wall-clock time (ms)
metadata dict Arbitrary execution metadata

ToolError

ToolError is an exception class for structured tool failures:

Attribute Type Description
tool_name str Namespaced tool name
error_type str Category (e.g. RegistrationError)
details str Human-readable explanation

Registry

ToolRegistry is an in-memory, thread-safe registry:

  • register(spec) -- adds a tool; raises ToolError on name collision.
  • get(name) -- lookup by namespaced name; returns None if not found.
  • list_tools(namespace?, tool_type?) -- list with optional filters.
  • remove(name) -- unregister; returns bool.

All mutating operations are protected by threading.RLock.