Use an Action as an LLM tool¶
An LLM tool is an ordinary A11 Action. Its schema
already gives the runtime everything a model needs: a stable name, a useful
description, typed inputs, and typed outputs. The LLM adapter converts that
native schema to JSON Schema; the action handler remains normal application
code.
Define the action¶
import a11
LOOK_UP_ORDER = a11.ActionSchema(
name="look_up_order",
description="Return the current fulfilment status of an order.",
inputs={
"order_id": a11.ActionPortSchema(
name="order_id",
type="text/plain",
typeinfo=str,
required=True,
description="The customer-visible order number.",
)
},
outputs={
"status": a11.ActionPortSchema(
name="status",
type="text/plain",
typeinfo=str,
required=True,
)
},
)
async def look_up_order(action: a11.Action) -> None:
order_id = await action["order_id"].consume()
result = await orders.fetch_status(order_id) # Your application service.
await action["status"].put_final(result)
await action["status"].drain_and_close()
Descriptions matter: they tell the model when the tool is relevant and what a valid argument means. Keep them specific and avoid instructions that belong in the system prompt.
Convert the ActionSchema to JSON Schema¶
from a11.sdk.llm_tools.adapter import ToolAdapter
adapter = ToolAdapter(LOOK_UP_ORDER)
input_schema = adapter.input_schema
input_schema is suitable for a provider’s function/tool declaration:
The adapter maps Pydantic models, enums, unions, collections, and annotated
field constraints, and places reusable definitions in a root $defs. Streaming
ports become arrays. Inputs marked for runtime autofill are omitted because the
model must not supply values such as identity or session context.
For normal use, register the action and let the runner build the complete tool definition: