> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ziet.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Build and deploy your first AI agent in 5 minutes

## Overview

In this guide, you'll build a **flight booking agent** that works like a personal travel assistant.

Here's what it does:

* Searches Google and airline websites for the best flights
* Analyzes options and picks the top recommendations
* Sends you an approval email before booking anything
* Charges your card and confirms your booking

You'll learn how to build **actions** (search, scrape, book), connect **two agents** that work together, and deploy everything to production with one command.

**Time**: 10 minutes • **Level**: Beginner

## Prerequisites

<Steps>
  <Step title="Install Ziet">
    ```bash theme={null}
    pip install ziet
    ```
  </Step>

  <Step title="Set your API key">
    ```bash theme={null}
    export ZIET_API_KEY="your_api_key_here"
    ```

    [Create a key in the dashboard](https://dashboard.ziet.ai/developer)
  </Step>
</Steps>

## Step 1: Create Your Actions

Create a file called `flight_agent.py`:

```python theme={null}
from ziet import Action, Agent, memory
from ziet.integrations import google, apify, openai, stripe, sendgrid
from ziet import PickActionsStrategy, HandOffStrategy, ManualApprovalStrategy, input

@Action(
    id="search_flights",
    name="Search Flights",
    description="Search Google for flight prices",
    timeout=30,
    retries=2
)
def search_flights(origin: str, dest: str, date: str) -> list:
    """Search Google for flight information."""
    query = f"flights from {origin} to {dest} on {date}"
    
    # Use built-in Google integration
    results = google.search(query, num_results=10)
    
    # Store results in memory
    memory.add(key="search_results", value=results)
    
    return results


@Action(
    id="scrape_airline",
    name="Scrape Airline Website",
    description="Scrape airline website for detailed pricing",
    timeout=60
)
def scrape_airline(url: str) -> None:
    """Extract pricing details from airline website."""
    # Use built-in Apify integration
    data = apify.scrape(
        url=url,
        extract=[".price", ".flight-details", ".airline-name"]
    )
    
    # Store HTML body in memory for later analysis
    memory.add(key=url, value=data.get("html", ""))


@Action(
    id="generate_summary",
    name="Generate Summary",
    description="Generate summary report using LLM",
    timeout=30
)
def generate_summary() -> str:
    """Create a natural language summary of findings."""
    # Retrieve search results from memory
    search_results = memory.get("search_results")
    
    # Retrieve scraped data from memory
    scraped_data = []
    for result in search_results:
        url = result.get("url")
        if url:
            body = memory.get(url)
            if body:
                scraped_data.append({"url": url, "content": body[:500]})
    
    prompt = f"""
    Analyze these flight search results and provide a summary:
    
    Search Results:
    {search_results}
    
    Detailed Pricing:
    {scraped_data}
    
    Provide:
    1. Cheapest option
    2. Best value option
    3. Recommended choice with reasoning
    """
    
    response = openai.chat(
        messages=[{"role": "user", "content": prompt}],
        model="gpt-4o-mini"
    )
    
    # Store summary in memory
    memory.add(key="final_summary", value=response)
    
    return response


@Action(
    id="book_flight",
    name="Book Flight",
    description="Book the selected flight",
    timeout=60
)
def book_flight(flight_details: dict) -> dict:
    """Book the flight."""
    # Booking logic here
    booking = {
        "booking_id": f"BK{flight_details.get('id', '12345')}",
        "status": "confirmed"
    }
    memory.add(key="booking", value=booking)
    return booking


@Action(
    id="charge_payment",
    name="Charge Payment",
    description="Charge customer payment",
    timeout=30
)
def charge_payment(amount: int, email: str) -> dict:
    """Charge payment via Stripe."""
    payment = stripe.create_payment_intent(
        amount=amount * 100,
        currency="usd"
    )
    memory.add(key="payment", value=payment)
    return payment


@Action(
    id="send_confirmation",
    name="Send Confirmation",
    description="Send booking confirmation email",
    timeout=20
)
def send_confirmation(email: str) -> bool:
    """Send confirmation email."""
    # Retrieve booking from memory
    booking = memory.get("final_booking")
    
    sendgrid.send(
        to=email,
        subject=f"Flight Booked - {booking['booking_id']}",
        body=f"<h1>Booking Confirmed</h1><p>{booking['booking_id']}</p>",
        html=True
    )
    return True
```

## Step 2: Create Your Agents

Add the agent classes to `flight_agent.py`:

```python theme={null}
# Agent 1: Research and find flights
@PickActionsStrategy(picks=10, allow_repeats=True)
@HandOffStrategy(agents=["booking_agent"])
@Agent(
    id="research_agent",
    name="FlightResearcher",
    description="Research and analyze flight options",
    instructions="""
    You are a flight research agent. Your goal:
    1. Search Google for flights between the origin and destination
    2. Scrape top airline websites for detailed pricing
    3. Compare all options and identify the best 3-5 flights
    4. Store all findings in memory with key "flight_options"
    5. Hand off to the booking agent with your recommendations
    
    Prioritize value over just price. Consider flight duration, layovers, and airline quality.
    """,
    actions=["search_flights", "scrape_airline", "generate_summary"],
    model="gpt-4o-mini"
)
class FlightResearchAgent:
    pass  # Agent behavior is defined by instructions and strategies


# Agent 2: Book the selected flight
@ManualApprovalStrategy(signee=input.user_email, method="email")
@Agent(
    id="booking_agent",
    name="FlightBooker", 
    description="Book flights after user approval",
    instructions="""
    You are a flight booking agent. Your workflow:
    1. Retrieve flight options from memory (key: "flight_options")
    2. Select the best flight based on the research
    3. Request user approval via email before booking
    4. After approval: book the flight using book_flight action
    5. Send confirmation email
    6. Store booking confirmation in memory
    
    Always wait for explicit approval before charging or booking.
    """,
    actions=["book_flight", "charge_payment", "send_confirmation"],
    model="gpt-4o-mini"
)
class FlightBookingAgent:
    pass  # Agent behavior is defined by instructions and strategies
```

## Step 3: Test Locally

Test your agent locally before deploying:

```bash theme={null}
ziet run --local --agent research_agent
```

This runs your agent in local mode with test data. You'll see:

* Actions being called
* Memory operations
* Integration calls (mocked locally)
* Agent handoffs
* Strategy execution

Expected output:

```
🧪 Running agent locally: research_agent

[INFO] Starting local run...
[INFO] Agent research_agent initialized
[INFO] PickActionsStrategy: Selecting 10 actions
[INFO] Action search_flights started
[INFO] google.search returned 10 results (mocked)
[INFO] Memory added: key=search_results
[INFO] Action search_flights completed in 0.23s
[INFO] Action scrape_airline started (x3)
[INFO] Memory added: key=https://...
[INFO] Action generate_summary started
[INFO] Memory retrieved: search_results
[INFO] OpenAI chat completed
[INFO] Memory added: key=final_summary
[INFO] HandOffStrategy: Handing off to booking_agent
✅ Local run completed

Results: {...}
```

## Step 4: Deploy to Production

Deploy your agent with one command:

```bash theme={null}
ziet deploy
```

Output:

```
🚀 Deploying to Ziet...

✓ Analyzing code...
✓ Building agents...
✓ Uploading to cloud...
✓ Configuring infrastructure...

✅ Deployment successful!

Deployed 2 agents:
- research_agent: FlightResearcher
- booking_agent: FlightBooker

Actions deployed: 6
- search_flights, scrape_airline, generate_summary
- book_flight, charge_payment, send_confirmation

Endpoints:
  https://api.ziet.ai/agents/research_agent/run
  https://api.ziet.ai/agents/booking_agent/run

Dashboard: https://dashboard.ziet.ai/agents

Invoke via API:
  curl -X POST https://api.ziet.ai/agents/research_agent/run \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -d '{"origin": "SFO", "dest": "NYC", "user_email": "user@example.com"}'

Invoke via CLI:
  ziet run research_agent --origin "SFO" --dest "NYC" --user_email "user@example.com"
```

## Step 5: Invoke Your Agent

### Via API

```bash theme={null}
curl -X POST https://api.ziet.ai/agents/research_agent/run \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "origin": "SFO",
    "dest": "NYC",
    "date": "2024-12-25",
    "user_email": "user@example.com"
  }'
```

### Via CLI

```bash theme={null}
ziet run research_agent \
  --origin "SFO" \
  --dest "NYC" \
  --date "2024-12-25" \
  --user_email "user@example.com"
```

### Via Python SDK

```python theme={null}
from ziet import Client

client = Client(api_key="your_api_key")

result = client.run_agent(
    agent_id="research_agent",
    data={
        "origin": "SFO",
        "dest": "NYC",
        "date": "2024-12-25",
        "user_email": "user@example.com"
    }
)

print(result)
```

### Via Dashboard

1. Go to [dashboard.ziet.ai](https://dashboard.ziet.ai)
2. Navigate to **Agents** → **research\_agent**
3. Click **Run Agent**
4. Fill in the input form:
   * origin: "SFO"
   * dest: "NYC"
   * date: "2024-12-25"
   * user\_email: "[your@email.com](mailto:your@email.com)"
5. Click **Execute**

## Next Steps

<CardGroup cols={2}>
  <Card title="Actions" icon="bolt" href="/core/actions">
    Deep dive into actions
  </Card>

  <Card title="Agents" icon="robot" href="/core/agents">
    Master agent orchestration
  </Card>

  <Card title="Strategies" icon="chess" href="/strategies/overview">
    Learn orchestration strategies
  </Card>

  <Card title="Integrations" icon="plug" href="/integrations/overview">
    Explore all available integrations
  </Card>
</CardGroup>

## Common Patterns

<AccordionGroup>
  <Accordion title="Add error handling" icon="shield">
    ```python theme={null}
    @Action(
        id="safe_action",
        name="Safe Action",
        description="Action with error handling",
        timeout=30,
        retries=3
    )
    def safe_action(data: dict) -> dict:
        try:
            result = process_data(data)
            memory.add(key="success", value=result)
            return result
        except Exception as e:
            memory.add(key="error", value={"error": str(e)})
            raise
    ```
  </Accordion>

  <Accordion title="Use environment variables" icon="key">
    ```python theme={null}
    import os

    @Action(
        id="call_external_api",
        name="Call External API",
        description="Call external API with credentials"
    )
    def call_api(endpoint: str) -> dict:
        api_key = os.getenv("EXTERNAL_API_KEY")
        # Use api_key...
    ```

    Set in dashboard: [**Developer** → **Environment Variables**](https://dashboard.ziet.ai/developer)
  </Accordion>

  <Accordion title="Agent with multiple strategies" icon="layer-group">
    ```python theme={null}
    @PickActionsStrategy(picks=5, allow_repeats=False)
    @WaitStrategy(memory=["data_ready"], timeout=300)
    @HandOffStrategy(agents=["processing_agent"])
    @Agent(
        id="analysis_agent",
        name="AnalysisAgent",
        instructions="Process data when ready, pick best 5 actions, then hand off",
        actions=["action_1", "action_2", "action_3", "action_4", "action_5"]
    )
    class AnalysisAgent:
        pass
    ```
  </Accordion>

  <Accordion title="Search memory semantically" icon="magnifying-glass">
    ```python theme={null}
    @Action(
        id="analyze_options",
        name="Analyze Options",
        description="Analyze stored options"
    )
    def analyze_options(query: str) -> list:
        # Semantic search across all memories
        results = memory.search("cheapest flight option", limit=5)
        
        best_options = [entry["value"] for entry in results]
        return best_options
    ```
  </Accordion>
</AccordionGroup>

## Need Help?

<CardGroup cols={2}>
  <Card title="Join Discord" icon="discord" href="https://discord.gg/ziet">
    Get help from the community
  </Card>

  <Card title="Email Support" icon="envelope" href="mailto:alex@ziet.ai">
    Contact the team directly
  </Card>
</CardGroup>
