Skip to content
Bifrost Docs

AI Tools

Make workflows callable by AI agents

Mark workflows as tools so AI agents can call them during conversations. The decorator still only carries identity metadata; the tool-specific prompt text lives in the workflow record or UI.

Add is_tool=True and use the workflow description for the agent-facing summary:

from bifrost import workflow
@workflow(
is_tool=True,
description="Look up a customer by email and return their account details"
)
async def lookup_customer(email: str):
"""Look up customer information."""
customer = await get_customer(email)
return {
"name": customer.name,
"account_id": customer.id,
"status": customer.status
}
Parameter Type Description
is_tool bool Make callable by AI agents
description str Description the AI uses to understand when to call this tool
  1. Assign the workflow as a tool to an AI agent
  2. When chatting, the agent decides when to call the tool
  3. Agent passes parameters extracted from conversation
  4. Tool result is included in agent’s response

The workflow description helps the AI know when to use the tool:

# Good - specific about what it does and when to use it
@workflow(
is_tool=True,
description="Search for support tickets by keyword. Use when the user asks about existing tickets or wants to find tickets matching a description."
)
async def search_tickets(query: str, limit: int = 10):
...
# Bad - too vague
@workflow(
is_tool=True,
description="Search tickets"
)
async def search_tickets(query: str):
...

Keep parameters simple for AI extraction:

# Good - clear, typed parameters
@workflow(
is_tool=True,
description="Create a new support ticket for a customer"
)
async def create_ticket(
customer_email: str,
subject: str,
description: str,
priority: str = "normal" # low, normal, high
):
...
# Avoid - complex nested structures
@workflow(is_tool=True, ...)
async def create_ticket(ticket_data: dict): # AI can't know the structure
...

Return structured data the agent can use:

@workflow(
is_tool=True,
description="Get account balance for a customer"
)
async def get_balance(customer_id: str):
account = await fetch_account(customer_id)
return {
"customer_id": customer_id,
"balance": account.balance,
"currency": "USD",
"last_payment": account.last_payment_date
}
  1. Go to Agents in the sidebar
  2. Edit or create an agent
  3. In Tools, add your workflow
  4. Save

The agent can now call this tool during conversations.

from bifrost import workflow
@workflow(
is_tool=True,
description="Look up customer by email to get their account details and history"
)
async def lookup_customer(email: str):
customer = await get_customer(email)
return {
"id": customer.id,
"name": customer.name,
"email": customer.email,
"tier": customer.tier,
"total_orders": len(customer.orders)
}
@workflow(
is_tool=True,
description="Get recent orders for a customer. Use after looking up the customer."
)
async def get_orders(customer_id: str, limit: int = 5):
orders = await fetch_orders(customer_id, limit)
return [
{"id": o.id, "date": o.date, "total": o.total, "status": o.status}
for o in orders
]
@workflow(
is_tool=True,
description="Issue a refund for an order. Requires order ID and reason."
)
async def issue_refund(order_id: str, reason: str):
result = await process_refund(order_id, reason)
return {"success": True, "refund_id": result.id}
User: "I need help with my order"
Agent: "I'd be happy to help. What's your email?"
User: "john@example.com"
Agent: [calls lookup_customer("john@example.com")]
Agent: "Hi John! I found your account. What order do you need help with?"
User: "My last order hasn't arrived"
Agent: [calls get_orders("cust_123", limit=5)]
Agent: "I see order #456 from Dec 20th is marked as shipped..."