Skip to content

Tools Capability Specification

Capability Identity

PropertyValue
EnumA2ECapability.TOOLS
String"tools"
Plugin TypeToolPlugin
Namespacetool/*
Message Count5

Overview

The tools capability provides native environment tool execution — primitive, stateless operations like file I/O, shell commands, HTTP requests, and code evaluation. Tools are the most fundamental building block for agent interaction with the host environment. Unlike skills (which are multi-step and LLM-driven), tools are synchronous, request/response-based, and optionally streaming.

Protocol Flow

Message Types (5)

tool/list/req — ToolListRequest

Agent → Host. List or search available native tools.

When query is empty (default): returns non-deferred tools only (the active set). When query is set: searches tools by name/description/tags, including deferred ones if include_deferred is True.

FieldTypeRequiredDefaultDescription
typestrYes"tool/list/req"Message type identifier
idstrYesauto UUIDMessage UUID
versionstrYes"1.0"Protocol version
tsfloatYesautoUnix epoch timestamp
filter_kindstrNo""Tool kind filter (empty = all)
filter_tagslist[str]No[]Tag filter list (AND semantics)
querystrNo""Search query — empty = list mode, non-empty = search mode
include_deferredboolNoFalseInclude deferred tools in results (search mode)

tool/list/resp — ToolListResponse

Host → Agent. Returns all available tool manifests.

FieldTypeRequiredDefaultDescription
typestrYes"tool/list/resp"Message type identifier
idstrYesauto UUIDMessage UUID
versionstrYes"1.0"Protocol version
tsfloatYesautoUnix epoch timestamp
req_idstrYes""Echoes request ID
toolslist[ToolDefinition]Yes[]Available tool definitions

tool/call/req — ToolCallRequest

Agent → Host. Execute a native tool.

FieldTypeRequiredDefaultDescription
typestrYes"tool/call/req"Message type identifier
idstrYesauto UUIDMessage UUID
versionstrYes"1.0"Protocol version
tsfloatYesautoUnix epoch timestamp
session_idstrYes""Session from HandshakeResponse
tool_namestrYesMust match ToolDefinition.name
argumentsdictYesInput arguments validated against tool schema
correlation_idstrNo""Ties this call to an agent turn for tracing
streamingboolNoFalseIf True, host emits ToolEvent messages before final resp
timeoutintNo30Per-call wall-clock limit (seconds)

tool/call/resp — ToolCallResponse

Host → Agent. Final result of a tool call.

FieldTypeRequiredDefaultDescription
typestrYes"tool/call/resp"Message type identifier
idstrYesauto UUIDMessage UUID
versionstrYes"1.0"Protocol version
tsfloatYesautoUnix epoch timestamp
req_idstrYes""Echoes request ID
dataToolResultYesTool execution result
created_atfloatNoautoResult creation timestamp

tool/event — ToolEvent

Host → Agent. Zero or more streaming events during a tool call. Extends A2EEvent.

FieldTypeRequiredDefaultDescription
typestrYes"tool/event"Message type identifier
idstrYesauto UUIDMessage UUID
versionstrYes"1.0"Protocol version
tsfloatYesautoUnix epoch timestamp
kindstrYesEvent kind (see below)
req_idstrYes""Correlates to ToolCallRequest ID
datadictYes{}Event payload
seqintYes0Monotonic sequence number

Event kinds and their data shapes:

KindData ShapeDescription
progress{ "pct": int, "message": str }Progress update
status{ "message": str }One-liner status update
artifact{ "name": str, "mime": str, "chunk": str, "final": bool }Partial/incremental data chunk
log{ "level": str, "message": str }Debug log line

Data Models

ToolDefinition

FieldTypeRequiredDefaultDescription
namestrYesUnique tool name (e.g. "read_file")
descriptionstrYesHuman-readable description
input_parameterslist[ToolParameter]No[]Input parameter schema
output_parameterslist[ToolParameter]No[]Output parameter schema
streamingboolNoTrueSupports streaming events
idempotentboolNoFalseSafe to retry on failure
tagslist[str]No[]Classification tags
versionstrNo"1.0.0"Tool version
toolkitstrNoNoneParent toolkit name
defer_loadingboolNoFalseExclude from initial list; discoverable via search

ToolParameter

FieldTypeRequiredDefaultDescription
namestrYesParameter name
typestrYesJSON Schema type: string, integer, boolean, object, array
descriptionstrYesParameter description
requiredboolNoFalseWhether this parameter is required
enumlist[str]NoNoneAllowed values for enum types
propertiesdict[str, ToolParameter]NoNoneNested properties for object types

ToolResult

FieldTypeRequiredDefaultDescription
successboolYesWhether execution succeeded
tool_namestrYesTool that produced this result
dataAnyNoNoneResult data
summaryAnyNoNoneHuman-readable summary
truncatedboolNoFalseOutput was truncated
exit_codeintNoNoneProcess exit code (if applicable)
errorstrNoNoneError message
error_codestrNoNoneMachine-readable error code
duration_msintYesExecution time in milliseconds
eventslist[ToolEvent]No[]Collected streaming events

Error Codes — ToolErrorCode

CodeEnum ValueDescriptionRetryable
unknown_toolUNKNOWN_TOOLTool name not found in registryNo
tool_deniedTOOL_DENIEDTool not allowed by policy/capability checkNo
tool_errorTOOL_ERRORTool execution failedYes

Plugin Contract — ToolPlugin

python
class ToolPlugin(A2EPlugin):
    name = "base_tool"

    @abstractmethod
    def _list_tools(self) -> list[ToolDefinition]:
        """Must return tool manifest."""

    @abstractmethod
    def _execute_tool(self, tool_name: str, arguments: dict) -> dict:
        """Execute tool logic. Returns JSON-serializable dict.
        Raise exception for failure."""

    def _search_tools(
        self,
        query: str,
        filter_tags: list[str] | None = None,
        tools: list[ToolDefinition] | None = None,
    ) -> list[ToolDefinition]:
        \"\"\"On-demand tool discovery. Default: substring match on name/description/tags.
        Override for BM25, embeddings, or custom search strategies.\"\"\"

    def set_event_callback(self, fn: Callable[[ToolEvent], None]):
        \"\"\"Register streaming event callback.\"\"\"

    def emit(self, kind: str, data: dict):
        \"\"\"Emit streaming event during execution.\"\"\"

Handler dispatch:

  • ToolListRequest with empty query → calls _list_tools(), filters out defer_loading=True, returns ToolListResponse
  • ToolListRequest with non-empty query → calls _search_tools(query, filter_tags) for on-demand discovery, returns ToolListResponse
  • ToolCallRequest → attaches streaming callback, calls _execute_tool(), returns ToolCallResponse or A2EError

Execution wrapper: _execute() provides safe execution with:

  • Error catching and conversion to A2EError
  • Streaming event emission via emit()
  • Audit logging via self.audit_handle()

Client API — ToolAPI

python
from a2e.caps.tools.client import ToolAPI

tools = ToolAPI(client)

# List active (non-deferred) tools — the ~500-token set the model should see
tool_list = tools.list()
# Returns List[ToolDefinition], cached in client._tools_cache

# Search all tools by name/description/tags (including deferred)
search_results = tools.list(query="github", include_deferred=True)
for t in search_results:
    print(f"  {t.name}: {t.description}")

# Filter by tags
network_tools = tools.list(tags=["network"])
print(f"Network tools: {[t.name for t in network_tools]}")

# Call a tool
result = tools.call(
    tool_name="read_file",
    arguments={"path": "/etc/hostname"},
    streaming=False,
    on_event=None,          # Callback for ToolEvents
    timeout=30.0,
    correlation_id=None
)
# Returns ToolResult

if result.success:
    print(result.data)
else:
    print(f"Error: {result.error_code} - {result.error}")

Wire Examples

List Tools

json
{"type":"tool/list/req","id":"a1b2c3","version":"1.0","ts":1716123456.789,"filter_kind":"","filter_tags":[]}
json
{"type":"tool/list/resp","id":"d4e5f6","version":"1.0","ts":1716123456.800,"req_id":"a1b2c3","tools":[{"name":"read_file","description":"Read file contents","input_parameters":[{"name":"path","type":"string","description":"File path","required":true}],"output_parameters":[],"streaming":true,"idempotent":true,"tags":["fs"],"version":"1.0.0","toolkit":null}]}

Call Tool (with streaming)

json
{"type":"tool/call/req","id":"g7h8i9","version":"1.0","ts":1716123457.100,"session_id":"s1k2l3","tool_name":"read_file","arguments":{"path":"/etc/hostname"},"correlation_id":"","streaming":true,"timeout":30}
json
{"type":"tool/event","id":"j0k1l2","version":"1.0","ts":1716123457.150,"kind":"progress","req_id":"g7h8i9","data":{"pct":50,"message":"Reading..."},"seq":0}
json
{"type":"tool/call/resp","id":"m3n4o5","version":"1.0","ts":1716123457.200,"req_id":"g7h8i9","data":{"success":true,"tool_name":"read_file","data":{"content":"my-host"},"duration_ms":100},"created_at":1716123457.200}

Security Considerations

  1. Capability gating: Tools require the tools capability to be negotiated during handshake
  2. Policy enforcement: Host may deny tool execution via TOOL_DENIED error code
  3. Timeout enforcement: Per-call timeout prevents runaway tool execution (default: 30s)
  4. Input validation: Arguments validated against ToolParameter schema before execution
  5. Audit trail: All tool calls are logged via audit_handle()

A2E Protocol v1.0 — Released under the MIT License.