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

# Agents

> Understanding agents and how to use them in the mcp-agent framework.

## What is an Agent?

In `mcp-agent`, an **Agent** describes what the model is allowed to do. It captures:

* A name and system-level instruction
* The MCP servers (and optional local functions) that should be available
* Optional behaviour hooks such as human-input callbacks or whether connections persist

On its own an agent is just configuration and connection management. The agent becomes actionable only after you attach an LLM implementation. Calling `agent.attach_llm(...)` (or constructing an AugmentedLLM with `agent=...`) returns an **AugmentedLLM**—an LLM with the agent’s instructions, tools, and memory bound in. You then use the AugmentedLLM to run generations, call tools, and chain workflows.

Key ideas:

* **Agent = policy + tool access.** It defines how the model should behave and which MCP servers or functions are reachable.
* **AugmentedLLM = Agent + model provider.** Attaching an LLM binds a concrete provider (OpenAI, Anthropic, Google, Bedrock, etc.) and exposes generation helpers such as `generate`, `generate_str`, and `generate_structured`.
* **Agents are reusable.** You can attach different AugmentedLLM providers to the same agent definition without rewriting instructions or server lists.

## Creating Your First Agent

The simplest way to create an agent is through the `Agent` class. Define the instruction and servers, then attach an LLM to obtain an AugmentedLLM:

```python theme={null}
from mcp_agent.agents.agent import Agent
from mcp_agent.workflows.llm.augmented_llm_openai import OpenAIAugmentedLLM

# Create an agent with access to specific tools
finder_agent = Agent(
    name="finder",
    instruction="""You are an agent with access to the filesystem
    and web fetching capabilities. Your job is to find and retrieve
    information based on user requests.""",
    server_names=["fetch", "filesystem"],
)

# Use the agent in an async context
async with finder_agent:
    # Attach an LLM to the agent
    llm = await finder_agent.attach_llm(OpenAIAugmentedLLM)

    # Generate a response
    result = await llm.generate_str(
        message="Find and show me the contents of the README file"
    )
    print(result)
```

The value returned by `attach_llm` is an `AugmentedLLM` instance. It inherits the agent’s instructions and tool access, so every call to `generate_str` (or `generate` / `generate_structured`) can transparently read files, fetch URLs, or call any other MCP tool the agent exposes.

<CardGroup>
  <Card title="Tool Integration">
    Agents automatically discover and use tools from connected MCP servers,
    giving your LLM powerful capabilities.
  </Card>

  <Card title="Multi-Provider Support">
    Switch between different LLM providers (OpenAI, Anthropic, etc.) without
    changing your agent logic.
  </Card>
</CardGroup>

## AgentSpec and factory helpers

`AgentSpec` (`mcp_agent.agents.agent_spec.AgentSpec`) is the declarative version of an agent: it captures the same fields (`name`, `instruction`, `server_names`, optional functions) and is used by workflows, config files, and factories. The helpers in [`mcp_agent.workflows.factory`](https://github.com/lastmile-ai/mcp-agent/blob/main/src/mcp_agent/workflows/factory.py) let you turn specs into agents or AugmentedLLMs with a single call.

```python theme={null}
from pathlib import Path
from mcp_agent.workflows.factory import (
    load_agent_specs_from_file,
    create_llm,
    create_router_llm,
)

async with app.run() as running_app:
    context = running_app.context
    specs = load_agent_specs_from_file(
        str(Path("examples/basic/agent_factory/agents.yaml")),
        context=context,
    )

    # Create a specialist LLM from a spec
    researcher_llm = create_llm(agent=specs[0], provider="openai", context=context)

    # Or compose higher-level workflows (router, parallel, orchestrator, ...)
    router = await create_router_llm(agents=specs, provider="openai", context=context)
```

Explore the [agent factory examples](https://github.com/lastmile-ai/mcp-agent/tree/main/examples/basic/agent_factory) to see how specs keep call sites small, how subagents can be auto-loaded from config, and how factories compose routers, orchestrators, and parallel pipelines.

## Agent Configuration

Agents can be configured either programmatically or through configuration files. The framework supports both approaches, and each definition ultimately resolves to an `AgentSpec`:

### Configuration File Approach

Create a `mcp_agent.config.yaml` file to define your agent's environment:

```yaml theme={null}
# mcp_agent.config.yaml
$schema: ../../schema/mcp-agent.config.schema.json

execution_engine: asyncio

# Configure logging
logger:
  transports: [console, file]
  level: debug
  progress_display: true

# Define available MCP servers (tools)
mcp:
  servers:
    fetch:
      command: "uvx"
      args: ["mcp-server-fetch"]
    filesystem:
      command: "npx"
      args: ["-y", "@modelcontextprotocol/server-filesystem"]

# LLM provider configuration
openai:
  default_model: "gpt-4o-mini"
```

### Programmatic Configuration

You can also configure agents directly in code:

```python theme={null}
from mcp_agent.config import Settings, MCPSettings, MCPServerSettings

settings = Settings(
    execution_engine="asyncio",
    mcp=MCPSettings(
        servers={
            "fetch": MCPServerSettings(
                command="uvx",
                args=["mcp-server-fetch"],
            ),
            "filesystem": MCPServerSettings(
                command="npx",
                args=["-y", "@modelcontextprotocol/server-filesystem"],
            ),
        }
    ),
    openai=OpenAISettings(
        default_model="gpt-4o-mini",
    ),
)
```

## Agent Capabilities

Once an agent has an AugmentedLLM attached, it gains the following capabilities:

### Multi-LLM Provider Support

Switch between different LLM providers seamlessly:

```python theme={null}
from mcp_agent.workflows.llm.augmented_llm_openai import OpenAIAugmentedLLM
from mcp_agent.workflows.llm.augmented_llm_anthropic import AnthropicAugmentedLLM

async with agent:
    # Start with OpenAI
    llm = await agent.attach_llm(OpenAIAugmentedLLM)
    result1 = await llm.generate_str("Analyze this data...")

    # Switch to Anthropic for the next task
    llm = await agent.attach_llm(AnthropicAugmentedLLM)
    result2 = await llm.generate_str("Summarize the analysis...")
```

### Advanced Model Selection

Control model selection with preferences:

```python theme={null}
from mcp_agent.workflows.llm.augmented_llm import RequestParams
from mcp_agent.workflows.llm.llm_selector import ModelPreferences

result = await llm.generate_str(
    message="Complex reasoning task",
    request_params=RequestParams(
        modelPreferences=ModelPreferences(
            costPriority=0.1,        # Low cost priority
            speedPriority=0.2,       # Low speed priority
            intelligencePriority=0.7  # High intelligence priority
        ),
        temperature=0.3,
        maxTokens=1000,
    )
)
```

### Human Input Integration

Agents can request human input during execution:

```python theme={null}
# The agent can automatically request human input when needed
# This is handled through the human_input_callback mechanism
# and appears as a tool the LLM can call
from mcp_agent.human_input.handler import console_input_callback

app = MCPApp(name="my_application", human_input_callback=console_input_callback)

# ...rest of your code

result = await llm.generate_str(
    "Please review this analysis and ask me any questions you need clarification on."
)
```

### Memory and Context Management

Agents maintain conversation history automatically:

```python theme={null}
# Multi-turn conversations maintain context
result1 = await llm.generate_str("What's the weather like?")
result2 = await llm.generate_str("What about tomorrow?")  # Remembers context
```

## Agent Lifecycle Management

Agents follow a predictable lifecycle:

### 1. Initialization

When you create an agent, it:

* Loads configuration from files or code
* Connects to specified MCP servers
* Discovers available tools and capabilities

### 2. Usage

During operation, the agent:

* Processes user requests through the LLM
* Orchestrates tool calls as needed
* Maintains conversation history
* Handles errors and retries

### 3. Cleanup

When finished, the agent:

* Closes connections to MCP servers
* Releases resources
* Saves any persistent state

```python theme={null}
# Explicit lifecycle management
agent = Agent(name="my_agent", server_names=["fetch"])

# Initialize
await agent.initialize()

# Use
llm = await agent.attach_llm(OpenAIAugmentedLLM)
result = await llm.generate_str("Hello!")

# Cleanup
await agent.shutdown()

# Or use context manager (recommended)
async with Agent(name="my_agent", server_names=["fetch"]) as agent:
    llm = await agent.attach_llm(OpenAIAugmentedLLM)
    result = await llm.generate_str("Hello!")
    # Automatic cleanup when exiting context
```

## Common Usage Patterns

### Application Integration

Use the `MCPApp` class for full application setup:

```python theme={null}
from mcp_agent.app import MCPApp

app = MCPApp(name="my_application")

async def main():
    async with app.run() as agent_app:
        logger = agent_app.logger
        context = agent_app.context

        # Create and use agents within the app context
        agent = Agent(
            name="assistant",
            instruction="You are a helpful assistant.",
            server_names=["filesystem", "fetch"]
        )

        async with agent:
            llm = await agent.attach_llm(OpenAIAugmentedLLM)
            result = await llm.generate_str("Help me organize my files")
            logger.info("Task completed", data={"result": result})
```

### Tool Discovery

Explore what tools are available to your agent:

```python theme={null}
async with agent:
    # List all available tools
    tools = await agent.list_tools()
    print(f"Available tools: {[tool.name for tool in tools.tools]}")

    # Get detailed tool information
    for tool in tools.tools:
        print(f"Tool: {tool.name}")
        print(f"Description: {tool.description}")
        print(f"Input schema: {tool.inputSchema}")
```

This covers the essential concepts users need to understand and effectively use agents in the mcp-agent framework.
