Building with the CugaAgent SDK
Single agent
from cuga import CugaAgent
from langchain_core.tools import tool
import asyncio
@tool
def add_numbers(a: int, b: int) -> int:
"""Add two numbers together"""
return a + b
agent = CugaAgent(tools=[add_numbers])
async def main():
result = await agent.invoke("What is 5 + 3?")
print(result.answer)
asyncio.run(main())
Key points:
- Tools are plain LangChain
@tool-decorated functions (or an OpenAPI/MCP provider — seecuga-build-tool). await agent.invoke(message, thread_id=...)—thread_idisolates conversation state per user/session; omit it for a one-off call.agent.stream()gives real-time execution events instead of a single final result.agent.policiesis the entry point for attaching Intent Guard / Playbook / Tool Approval / Tool Guide / Output Formatter policies programmatically — seecuga-author-policy.- Knowledge/RAG is on by default (
enable_knowledge=True) — seecuga-knowledge-rag; passenable_knowledge=Falseto turn it off. - The underlying LangGraph graph is reachable for advanced use cases (custom nodes, inspecting state) if the simple API isn't enough.
Multi-agent (CugaSupervisor)
from cuga import CugaAgent, CugaSupervisor
from langchain_core.tools import tool
import asyncio
@tool
def get_customers(limit: int = 10) -> str:
"""Fetch top customers from CRM."""
return "Alice ($250k); Bob ($180k)"
@tool
def send_email(to: str, body: str) -> str:
"""Send an email."""
return f"Email sent to {to}"
async def main():
crm_agent = CugaAgent(tools=[get_customers])
crm_agent.description = "CRM and customer data"
email_agent = CugaAgent(tools=[send_email])
email_agent.description = "Sending emails and notifications"
supervisor = CugaSupervisor(agents={"crm": crm_agent, "email": email_agent})
result = await supervisor.invoke("Get our top customer and email them a thank-you")
print(result.answer)
asyncio.run(main())
- Each sub-agent needs a
.description— the supervisor uses it to decide who handles what. - Mix local
CugaAgents with remote agents via A2A: pass an"agent_name": {"type": "external", "description": "...", "config": {"a2a_protocol": {...}}}entry inagents=. - Pass data between sub-agents with
variables=["var_name"]. CugaSupervisor.from_yaml("path/to/config.yaml")loads agents from a config file instead of constructing them in code.- Try it live first:
uv run cuga start demo_supervisor(seecuga-install-and-launch).
Reference
Full SDK docs: https://docs.cuga.dev/docs/sdk/cuga_agent/ and https://docs.cuga.dev/docs/sdk/cuga_supervisor