ComposioComposio 0.21 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
8 small wins to finish your pathNext lesson

Custom tools

experimental.tool turns your own function into a tool alongside Composio's, with its input schema inferred from a Pydantic model and its description from the docstring.

Example
from pydantic import BaseModel, Field
from composio import Composio

composio = Composio(api_key="not-a-real-key", allow_tracking=False)

ORDERS = {"A-1001": "shipped on 12 March"}


class LookupInput(BaseModel):
    order_id: str = Field(description="The order id, like A-1001")

The tool's input is a Pydantic model; its field descriptions become part of the schema the model reads.

Example
@composio.experimental.tool
def lookup_order(input: LookupInput, ctx):
    """Look up the status of an order in the shop database."""
    return {"status": ORDERS.get(input.order_id, "no such order")}
Example
print(lookup_order.slug, "|", lookup_order.name)
print(lookup_order.description)
print(json.dumps(lookup_order.input_schema))

The decorator returned a CustomTool. From the function it inferred the slug LOOKUP_ORDER, a display name, the description from the docstring, and a JSON schema from LookupInput, with the field's description. No request was made: defining a custom tool is local.

Example
print(lookup_order.execute(LookupInput(order_id="A-1001"), ctx=None))
print(lookup_order.execute(LookupInput(order_id="A-9999"), ctx=None))

execute is your function. At run time Composio passes a ctx, which can call an app with the user's connection through ctx.proxy_execute; this function does not need it, so a test can pass None. Add the tool to a session with composio.use(session_id, custom_tools=[lookup_order]), or with experimental={"custom_tools": [lookup_order]} on create. Custom tools run in your process, not on Composio's servers.

Try it yourself
  • Add an optional field with a default to LookupInput and print the schema.
  • Pass slug="SHOP_LOOKUP_ORDER" to the decorator.
  • Read extends_toolkit in the decorator's docstring: what does it give a custom tool?

Every expert started right here.