Agents
Agents extend the AI SDK beyond simple prompt-response. Use run_agent when you need multi-step reasoning, tool use, or autonomous decision-making inside any stage.
When to use run_agent vs prompt
Use prompt when... | Use run_agent when... |
|---|---|
| You need a single answer or extraction | The task requires multiple steps or decisions |
| Input and output are well-defined | The agent needs to read files, query databases, or call APIs |
| No tools or external actions needed | Each step depends on the result of the previous one |
You want structured output with format | The task involves unstructured content (emails, documents, screenshots) |
Basic agent
from abstra.ai import run_agent
from abstra.tasks import get_trigger_task
task = get_trigger_task()
result = run_agent(
prompt=f"""
You are a customer support agent.
Customer: {task.payload.get("customer_name")}
Message: {task.payload.get("message")}
Classify this request and propose a response.
""",
max_steps=20,
)
print(result)
Agent with database access
Use TablesTools to let the agent query and modify your Abstra Tables.
from abstra.ai import run_agent, TablesTools
from abstra.tasks import get_trigger_task
task = get_trigger_task()
run_agent(
prompt=f"""
You received a support ticket:
- From: {task.payload.get("customer_email")}
- Subject: {task.payload.get("subject")}
- Message: {task.payload.get("message")}
Categorize this ticket by inserting a row into the `support_tickets` table with:
- email: the customer's email
- category: one of "billing", "technical", "general"
- priority: one of "low", "medium", "high"
- summary: a one-sentence summary of the issue
""",
tools=[TablesTools(method=["insert"], table="support_tickets")],
)
Read-only queries
from abstra.ai import run_agent, TablesTools
result = run_agent(
prompt="List all open tickets and summarize the most common categories.",
tools=[TablesTools(method=["select"], table="tickets")],
)
Multi-table with tenant scoping
from abstra.ai import run_agent, TablesTools
run_agent(
prompt="Process the pending orders for tenant abc.",
tools=[
TablesTools(
method="all",
table=["orders", "order_items"],
where={"tenant_id": "abc"},
)
],
)
Agent with file access
Use FilesTools to let the agent read, write, and manage files in your project.
from abstra.ai import run_agent, FilesTools
run_agent(
prompt="Read all files in data/ and create a summary report.",
tools=[FilesTools(actions=["read_text", "list"], globs=["data/*"])],
)
Parse and transform files
from abstra.ai import run_agent, FilesTools
run_agent(
prompt="Parse input.csv, clean the data, and write the result to output.csv.",
tools=[FilesTools(actions=["read_text", "write_text"], globs=["*.csv"])],
)
Agent with connectors
Use ConnectorsTools to let the agent call external services like Slack, Stripe, or email.
from abstra.ai import run_agent, ConnectorsTools
from abstra.tasks import get_trigger_task
task = get_trigger_task()
run_agent(
prompt=f"""
A new order was placed:
- Customer: {task.payload.get("customer_name")}
- Total: R${task.payload.get("total")}
- Items: {len(task.payload.get("items", []))} items
Send a summary to the #orders Slack channel.
""",
tools=[ConnectorsTools(connection="slack", action="send_message")],
)
Agent with browser automation
Use BrowserTools to give the agent a headless Chromium browser for web scraping, form filling, and screenshots.
from abstra.ai import run_agent, BrowserTools
result = run_agent(
prompt="""
Go to https://news.ycombinator.com and extract the top 5 stories.
For each story, get the title, URL, and point count.
""",
tools=[BrowserTools(url="https://news.ycombinator.com")],
max_steps=10,
)
Login and screenshot
from abstra.ai import run_agent, BrowserTools
run_agent(
prompt="""
Go to https://app.example.com/login, fill in user@test.com and password123,
click Login, then take a screenshot of the dashboard.
""",
tools=[BrowserTools(url="https://app.example.com")],
)
Debug with network and console tracking
from abstra.ai import run_agent, BrowserTools
run_agent(
prompt="Navigate to the page and check for any failed API calls or console errors.",
tools=[BrowserTools(
url="https://app.example.com",
listen_network=True,
listen_console=True,
)],
)
Agent with custom tools
Any Python function can be a tool. Use type hints and docstrings so the agent knows when and how to call it.
from abstra.ai import run_agent
def lookup_order(order_id: str) -> str:
"""Returns the status of a given order by its ID."""
orders = {
"123": "In transit - arriving March 15",
"456": "Delivered on March 10",
}
return orders.get(order_id, "Order not found")
def calculate_shipping(weight_kg: float, destination: str) -> str:
"""Calculates shipping cost based on weight and destination."""
base_cost = weight_kg * 5.0
if destination == "international":
base_cost *= 2.5
return f"R${base_cost:.2f}"
result = run_agent(
prompt="Check orders 123 and 456. Then calculate shipping for a 3kg international package.",
tools=[lookup_order, calculate_shipping],
)
print(result)
Agent with custom tools and workflow transitions
Use custom functions to route tasks to different stages based on the agent's reasoning.
from abstra.ai import run_agent, FilesTools
from abstra.tasks import get_trigger_task, send_task
task = get_trigger_task()
def approve(summary: str) -> str:
"""Mark the document as approved and forward it with a summary."""
send_task("approved", {"summary": summary})
return "Document approved and forwarded."
def reject(missing_fields: str) -> str:
"""Mark the document as rejected with the list of missing fields."""
send_task("rejected", {"missing_fields": missing_fields})
return "Document rejected and forwarded."
run_agent(
prompt=f"""
Review the following document submission:
- Type: {task.payload.get("document_type")}
- Submitted by: {task.payload.get("submitted_by")}
The document is stored at: {task.payload.get("file_path")}
Read the document and determine if it is complete. Then:
- If complete, call approve() with the document summary
- If incomplete, call reject() with the missing fields
""",
tools=[
FilesTools(actions=["read_text"], globs=[task.payload.get("file_path", "*")]),
approve,
reject,
],
)
Agent with images and PDFs
Pass files directly in the prompt list. Images and PDFs are automatically processed by the LLM.
from abstra.ai import run_agent, TablesTools
from abstra.tasks import get_trigger_task
task = get_trigger_task()
run_agent(
prompt=[
"""Extract the following information from the receipt:
- Store name
- Date
- Total amount
- List of items with prices
Insert the data into the `receipts` table.""",
task.payload.get("receipt_image"),
],
tools=[TablesTools(method=["insert"], table="receipts")],
)
Combining multiple toolkits
Mix built-in toolkits and custom functions. The agent decides which tools to use based on the prompt.
from abstra.ai import run_agent, TablesTools, FilesTools, ConnectorsTools
run_agent(
prompt="""
Read the CSV file with customer complaints, categorize each one,
insert the results into the complaints table, and send a Slack summary.
""",
tools=[
FilesTools(actions=["read_text"], globs=["complaints.csv"]),
TablesTools(method=["insert"], table="complaints"),
ConnectorsTools(connection="slack", action="send_message"),
],
)
Real-world example: Invoice processing pipeline
A complete agent that receives invoices, extracts data, validates, stores in database, and notifies via Slack.
from abstra.ai import run_agent, TablesTools, ConnectorsTools
from abstra.tasks import get_trigger_task, send_task
task = get_trigger_task()
invoice_path = task.payload.get("file_path")
def flag_for_review(reason: str) -> str:
"""Flag the invoice for manual review with the given reason."""
send_task("manual_review", {
"file_path": invoice_path,
"reason": reason,
})
return "Invoice flagged for manual review."
def mark_as_processed(invoice_data: dict) -> str:
"""Mark the invoice as successfully processed."""
send_task("processed", {
"file_path": invoice_path,
**invoice_data,
})
return "Invoice marked as processed."
run_agent(
prompt=[
f"""
You are an invoice processing agent. Analyze the attached invoice and:
1. Extract: vendor name, CNPJ, invoice number, date, line items, and total amount
2. Validate: check that line items sum to the total (within 1% tolerance)
3. Store the extracted data in the `invoices` table
4. If valid, call mark_as_processed with the extracted data
5. If there are discrepancies, call flag_for_review with the reason
6. Send a summary to the #finance Slack channel
""",
invoice_path,
],
tools=[
TablesTools(method=["insert", "select"], table="invoices"),
ConnectorsTools(connection="slack", action="send_message"),
flag_for_review,
mark_as_processed,
],
max_steps=15,
)
Tips
- Start small: Begin with specific, restricted toolsets rather than giving broad access.
- Use
max_steps: Keep it conservative (10-20) for focused tasks. The default of 30 is generous. - Clear prompts: Be explicit about the objective, constraints, and expected output.
- Type hints + docstrings: Always add them to custom tools — the agent reads them to decide which tool to use.
- Scope access: Prefer
table="orders"over unrestricted access,globs=["data/*"]over"*". - Use
wherefor multi-tenancy: Passwhere={"tenant_id": id}to scope all database operations.