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

# Agent Architecture

> Agent architecture in Agentor: how the Agent class handles configuration, tool registration, model calls, lifecycle, and synchronous or streaming execution.

## Overview

An Agentor agent is a model, a set of tools, and the loop that drives them. The loop calls the model; if the model asks for tools, the loop runs them and feeds the results back; it repeats until the model stops asking or the turn budget runs out.

Everything the loop does is emitted as an event. Streaming, the final result, [traces](/agentor/tracing), and [durable runs](/agentor/durable-runs) are all views of that one stream.

## Agent Class

The core `Agentor` class provides the primary interface for building agents:

```python theme={null} theme={null}
from agentor import Agentor

agent = Agentor(
    name="Weather Agent",
    instructions="You are a helpful weather assistant",
    model="gpt-5-mini",
    tools=["get_weather"],
)
```

### Constructor Parameters

<ParamField path="name" type="str" required>
  Agent name used in logs, traces, and A2A protocol agent cards
</ParamField>

<ParamField path="instructions" type="str">
  System prompt defining agent behavior and personality
</ParamField>

<ParamField path="model" type="str | Model" default="gpt-5-nano">
  Model identifier:

  * `"gpt-5-mini"` — OpenAI models
  * `"gemini/gemini-2.5-flash"` — a `provider/model` string, routed through LiteLLM
  * any name the provider recognises, when `base_url` is set
</ParamField>

<ParamField path="base_url" type="str">
  An OpenAI-compatible endpoint to use instead of OpenAI. See [Model providers](/agentor/model-providers).
</ParamField>

<ParamField path="tools" type="List[Callable | Tool | str | BaseTool | MCPServer]">
  Tools available to the agent. Can be:

  * String names from the tool registry (`"get_weather"`, `"current_datetime"`)
  * Functions decorated with `@function_tool`, or plain callables
  * `BaseTool` subclasses with `@capability` methods
  * `MCPServer` connections
</ParamField>

<ParamField path="output_type" type="type[BaseModel]">
  Pydantic model describing the shape of the answer. See [Structured output](/agentor/structured-output).
</ParamField>

<ParamField path="max_turns" type="int" default={20}>
  How many model calls a run may make before it ends with `status="max_turns"`.
</ParamField>

<ParamField path="store" type="Store">
  Where to save the run's events, so it can be resumed. See [Durable runs](/agentor/durable-runs).
</ParamField>

<ParamField path="model_settings" type="ModelSettings">
  Model configuration including temperature, top\_p, max\_tokens
</ParamField>

<ParamField path="skills" type="List[str]">
  Paths to skill directories (see [Skills](/agentor/concepts/skills))
</ParamField>

<ParamField path="enable_tracing" type="bool" default={false}>
  Enable Celesto AI tracing and observability
</ParamField>

<ParamField path="api_key" type="str">
  API key for the LLM provider
</ParamField>

## Creating Agents from Markdown

Agents can be defined in markdown files with YAML frontmatter:

```markdown theme={null} theme={null}
---
name: WeatherBot
tools: [get_weather]
model: gpt-4o-mini
temperature: 0.3
---
You are a concise weather assistant.
```

Load the agent:

```python theme={null} theme={null}
from agentor import Agentor

agent = Agentor.from_md("agent.md")
result = agent.run("Weather in Paris?")
```

## Agent Lifecycle

### Synchronous Execution

The `run()` method provides synchronous execution:

```python theme={null} theme={null}
result = agent.run("What is the weather in London?")
print(result)
```

### Asynchronous Execution

The `arun()` method supports async execution with batch processing:

```python theme={null} theme={null}
import asyncio

# Single prompt
result = await agent.arun("What is the weather in London?")

# Batch processing with concurrency control
results = await agent.arun(
    ["Weather in London?", "Weather in Paris?", "Weather in Tokyo?"],
    limit_concurrency=10,
    max_turns=20
)
```

#### Fallback Models

Handle rate limits gracefully with fallback models:

```python theme={null} theme={null}
result = await agent.arun(
    "Complex task",
    fallback_models=["gpt-4o-mini", "gemini/gemini-pro"]
)
```

If the primary model fails with rate limit or API errors, Agentor automatically retries with fallback models in order.

### Streaming Responses

Stream agent responses in real-time:

```python theme={null} theme={null}
async for chunk in agent.chat("Tell me about AI", stream=True):
    print(chunk, end="", flush=True)
```

The `stream_chat()` method returns an async iterator of `AgentOutput` objects:

```python theme={null} theme={null}
async for event in agent.stream_chat("Question", serialize=False):
    if event.message:
        print(event.message)
```

## Model Configuration

Configure model behavior with `ModelSettings`:

```python theme={null} theme={null}
from agentor import Agentor, ModelSettings

model_settings = ModelSettings(
    temperature=0.7,
    top_p=0.9,
    max_tokens=2000
)

agent = Agentor(
    name="Creative Writer",
    model="gpt-4o",
    model_settings=model_settings
)
```

## Multi-Agent Systems

Agents talk to each other over the [A2A protocol](/agentor/concepts/a2a-protocol). Call `agent.serve()` and each agent becomes an addressable service with a published agent card, so one agent can delegate to another across processes or machines.

## Agent Context

A tool can ask for the run's shared configuration by annotating a parameter as `RunContext`. That parameter is filled in by the engine rather than by the model, so it never appears in the tool's schema:

```python theme={null} theme={null}
from agentor.engine.tools import RunContext
from agentor.tools.registry import CelestoConfig, register_global_tool

@register_global_tool
def get_weather(wrapper: RunContext, city: str) -> str:
    """Returns the weather in the given city.

    Args:
        city: The city to look up.
    """
    api_key = wrapper.context.weather_api_key
    # Use API key to fetch weather
    return f"Weather in {city}"
```

<Note>
  The older `RunContextWrapper` annotation from openai-agents is still recognised, so tools written before 0.1.0 keep working without an edit.
</Note>

## Tracing and Observability

Opt in to tracing with Celesto AI:

```python theme={null} theme={null}
agent = Agentor(
    name="My Agent",
    model="gpt-4o",
    enable_tracing=True  # Requires CELESTO_API_KEY
)
```

Traces appear at `https://celesto.ai/observe`.

Tracing is off unless you ask for it, so there is nothing to disable. To exclude
a single run from an agent that has it on, pass `tracing=False` on that call.

## Next Steps

<CardGroup cols={2}>
  <Card title="Tools" icon="wrench" href="/agentor/concepts/tools">
    Learn how to add tools to your agents
  </Card>

  <Card title="Skills" icon="brain" href="/agentor/concepts/skills">
    Add specialized skills to improve agent performance
  </Card>

  <Card title="Deployment" icon="rocket" href="/agentor/concepts/deployment">
    Deploy your agent to production
  </Card>

  <Card title="A2A Protocol" icon="network-wired" href="/agentor/concepts/a2a-protocol">
    Enable agent-to-agent communication
  </Card>
</CardGroup>
