Skip to main content

What are Agents?

Agents are intelligent orchestrators that coordinate multiple actions to complete complex tasks. Unlike traditional scripts, agents are declarative - you define what they should do through instructions, not imperative code.
from ziet import Agent, Action, memory

@Agent(
    id="support_agent",
    name="CustomerSupport",
    description="Handle customer inquiries",
    instructions="""
    You are a customer support agent. Your workflow:
    1. Fetch customer data using fetch_customer action
    2. Get their latest order using get_order action
    3. Check shipment status using track_shipment action
    4. Store all results in memory
    5. Provide a helpful response to the customer
    
    Always be polite and provide tracking numbers when available.
    """,
    actions=["fetch_customer", "get_order", "track_shipment"],
    model="gpt-4o-mini"
)
class CustomerSupportAgent:
    pass  # Agent behavior is defined by instructions and strategies

Agent Parameters

Configure agent behavior with decorator parameters:
@Agent(
    id="search_agent",                    # Required: Unique identifier (use <verb>_agent)
    name="SearchAgent",                   # Required: Human-readable name
    description="Search and analyze",     # Optional: Description
    instructions="""...""",               # Required: Instructions for agent behavior
    actions=["action1", "action2"],       # Required: Available action IDs
    model="gpt-4o-mini",                  # Optional: LLM model
    max_steps=40                          # Optional: Max action calls per run
)
class MyAgent:
    pass  # Agent behavior is defined by instructions

Parameter Details

id
string
required
Unique identifier for the agent. Use <verb>_agent naming pattern.
@Agent(
    id="booking_agent",
    name="FlightBooker",
    instructions="...",
    actions=["book_flight"]
)
class FlightBooker:
    pass

# Deployed to: /agents/booking_agent/run
# CLI: ziet run booking_agent
name
string
required
Human-readable name displayed in the dashboard and logs.
@Agent(
    id="booking_agent",
    name="Flight Booking Agent",
    instructions="...",
    actions=["book_flight"]
)
class FlightBooker:
    pass
description
string
Description of what the agent does. Shown in dashboard and API docs.
@Agent(
    id="booking_agent",
    name="FlightBooker",
    description="Research airlines and book flights with approval",
    instructions="...",
    actions=["search_flights", "book_flight"]
)
class FlightBooker:
    pass
instructions
string
required
System prompt that defines agent behavior. This is how you tell the agent what to do, which actions to call, and how to handle scenarios. This is the core of your agent - think of it as the agent’s job description.
@Agent(
    id="booking_agent",
    name="FlightBooker",
    instructions="""
    You are a flight booking agent. Your workflow:
    1. Search for flights using search_flights action
    2. Compare prices and analyze options
    3. Store top 3 recommendations in memory with key 'top_flights'
    4. Book the selected flight using book_flight action
    5. Store booking confirmation in memory
    
    Always prioritize value over just cheapest price. Use memory to
    share data between steps.
    """,
    actions=["search_flights", "book_flight"]
)
class FlightBooker:
    pass
actions
list[string]
required
List of action IDs this agent can use. Agent can only call actions specified here.
@Agent(
    id="research_agent",
    name="ResearchAgent",
    instructions="Research topics using available actions",
    actions=["search_google", "scrape_website", "summarize_text"]
)
class ResearchAgent:
    pass
model
string
default:"gpt-4o-mini"
LLM model to use for AI-powered agents. Supported models:
  • gpt-4o-mini (default, fast and cheap)
  • gpt-4o (most capable)
  • gpt-4-turbo
  • claude-3-5-sonnet-20241022
  • claude-3-opus-20240229
@Agent(model="gpt-4o")  # Use GPT-4 for complex reasoning
class ComplexAgent:
    ...
max_steps
int
default:"40"
Maximum number of actions the agent can call in a single run. Prevents infinite loops.
@Agent(
    id="simple_agent",
    name="SimpleAgent",
    instructions="...",
    actions=["action1"],
    max_steps=20
)
class SimpleAgent:
    pass

Building Agents

Minimal Agent

The simplest agent with just instructions:
from ziet import Agent

@Agent(
    id="greeting_agent",
    name="GreetingAgent",
    instructions="Greet the user warmly and wish them a great day!",
    actions=[],
    model="gpt-4o-mini"
)
class GreetingAgent:
    pass  # Agent behavior is fully defined by instructions

Agent with Actions

An agent that uses actions to get work done:
from ziet import Agent, Action, memory
from ziet.integrations import google, openai

# Define actions
@Action(
    id="search_google",
    name="Search Google",
    description="Search Google for information"
)
def search_google(query: str) -> None:
    results = google.search(query, num_results=10)
    memory.add(key="search_results", value=results)

@Action(
    id="summarize_results",
    name="Summarize Results",
    description="Summarize search results using AI"
)
def summarize_results() -> None:
    results = memory.get("search_results")
    prompt = f"Summarize these search results: {results}"
    summary = openai.chat([{"role": "user", "content": prompt}])
    memory.add(key="final_summary", value=summary)

# Define agent
@Agent(
    id="research_agent",
    name="ResearchAgent",
    description="Research topics and provide summaries",
    instructions="""
    You are a research agent. Follow this workflow:
    1. Use search_google action to find information on the topic
    2. Store results in memory
    3. Use summarize_results action to create a concise summary
    4. All data should be stored in memory for retrieval
    
    Be thorough but concise. Focus on factual information.
    """,
    actions=["search_google", "summarize_results"],
    model="gpt-4o-mini",
    max_steps=20
)
class ResearchAgent:
    pass  # Agent orchestrates actions based on instructions

Using Memory

Actions store data in memory, and your agent instructions can reference that data:
from ziet import Agent, Action, memory

@Action(
    id="fetch_user",
    name="Fetch User",
    description="Fetch user from database"
)
def fetch_user(user_id: str) -> None:
    user = database.get_user(user_id)
    memory.add(key="current_user", value=user)

@Agent(
    id="profile_agent",
    name="ProfileAgent",
    instructions="""
    1. Use fetch_user action to get user data
    2. User data will be stored in memory with key 'current_user'
    3. Analyze the user profile and provide insights
    4. Store your analysis in memory with key 'profile_analysis'
    """,
    actions=["fetch_user"]
)
class ProfileAgent:
    pass
Learn more about Memory →

Using Integrations

Agents can use actions that leverage built-in integrations:
from ziet import Agent, Action, memory
from ziet.integrations import google, openai, stripe, sendgrid

@Action(
    id="search_flights",
    name="Search Flights",
    description="Search for flights using Google"
)
def search_flights(origin: str, dest: str) -> None:
    results = google.search(f"flights {origin} to {dest}")
    memory.add(key="flight_results", value=results)

@Action(
    id="analyze_flights",
    name="Analyze Flights",
    description="Analyze flight options with AI"
)
def analyze_flights() -> None:
    flights = memory.get("flight_results")
    prompt = f"Which flight offers best value? {flights}"
    analysis = openai.chat([{"role": "user", "content": prompt}])
    memory.add(key="flight_analysis", value=analysis)

@Agent(
    id="booking_agent",
    name="BookingAgent",
    instructions="""
    1. Search for flights using search_flights action
    2. Analyze options using analyze_flights action
    3. Present the best recommendation to the user
    """,
    actions=["search_flights", "analyze_flights"]
)
class BookingAgent:
    pass
View all integrations →

Testing Agents

Test your agent locally before deploying:
ziet run --local --agent research_agent
This runs your agent in local mode with test data. You’ll see:
  • Agent execution flow
  • Actions being called
  • Memory operations
  • Integration calls (mocked locally)
  • Strategy execution
Expected output:
🧪 Running agent locally: research_agent

[INFO] Starting local run...
[INFO] Agent research_agent initialized
[INFO] Calling action: search_google
[INFO] Memory added: key=search_results
[INFO] Calling action: summarize_results
[INFO] Memory added: key=final_summary
✅ Local run completed

Agent completed successfully

Deployment

Deploy your agent:
ziet deploy
After deployment, invoke via:
  • API
  • CLI
  • Python SDK
  • Dashboard
curl -X POST https://api.ziet.ai/agents/research_agent/run \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"topic": "quantum computing"}'

Best Practices

Each agent should have a clear, single purpose.Good: Separate agents for different workflows
@Agent(
    id="booking_agent",
    name="FlightBooker",
    instructions="Book flights after research and approval",
    actions=["book_flight", "charge_payment"]
)
class FlightBooker:
    pass

@Agent(
    id="hotel_agent",
    name="HotelBooker",
    instructions="Find and book hotels",
    actions=["search_hotels", "book_hotel"]
)
class HotelBooker:
    pass
Bad: One agent doing everything
@Agent(
    id="travel_agent",
    instructions="Books flights, hotels, cars, restaurants...",
    actions=["book_everything"]  # Too broad!
)
class TravelAgent:
    pass
Agent IDs should follow <verb>_agent pattern and be clear.Good
  • support_agent
  • research_agent
  • booking_agent
Bad
  • agent1
  • my-agent
  • test
Your instructions are the core of your agent - make them detailed and specific.
@Agent(
    id="research_agent",
    name="ResearchAgent",
    instructions="""
    You are a research agent. Follow this workflow:
    1. Use search_google action to find information on the topic
    2. Store results in memory with key 'search_results'
    3. Use summarize_text action to create a concise summary
    4. Store summary in memory with key 'final_summary'
    
    Expected input:
    - topic (string, required): Topic to research
    - depth (string, optional): "shallow" or "deep"
    
    Be thorough but concise. Focus on factual information.
    Always store intermediate results in memory for debugging.
    """,
    actions=["search_google", "summarize_text"]
)
class ResearchAgent:
    pass
Prevent runaway execution by setting reasonable limits.
# Simple agents
@Agent(
    id="greeting_agent",
    name="GreetingAgent",
    instructions="Greet the user",
    actions=[],
    max_steps=5
)
class GreetingAgent:
    pass

# Complex agents
@Agent(
    id="research_agent",
    name="ResearchAgent",
    instructions="...",
    actions=["search", "scrape", "summarize"],
    max_steps=50  # May need many searches and retries
)
class ResearchAgent:
    pass
Tell your agent how to use memory in the instructions.
@Agent(
    id="analysis_agent",
    name="AnalysisAgent",
    instructions="""
    Workflow:
    1. Fetch data using fetch_data action
    2. Data will be stored in memory with key 'raw_data'
    3. Analyze the data and identify key insights
    4. Store your analysis in memory with key 'analysis_result'
    5. Store top 3 recommendations in memory with key 'recommendations'
    
    Use memory to share data between actions and preserve context.
    """,
    actions=["fetch_data"]
)
class AnalysisAgent:
    pass
Only list actions the agent actually needs.
# Good: Specific actions for the task
@Agent(
    id="booking_agent",
    name="BookingAgent",
    instructions="...",
    actions=["search_flights", "compare_prices", "book_flight"]
)
class BookingAgent:
    pass

# Bad: Too many irrelevant actions
@Agent(
    id="booking_agent",
    name="BookingAgent",
    instructions="...",
    actions=["search_flights", "book_hotel", "rent_car", "book_restaurant"]
)
class BookingAgent:
    pass

Limitations

Current limitations:
  • Max execution time: 15 minutes per run
  • Max steps: Configurable, default 40
  • Declarative only: Agents use instructions, not imperative code
  • State in memory: All state must be stored in memory
  • No async actions: Parallel execution coming soon

Next Steps