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

# External Agents

> Integrate external AI coding CLI tools as PraisonAI agent tools

# External Agents

PraisonAI provides seamless integration with external AI coding CLI tools, allowing you to use Claude Code, Gemini CLI, Codex CLI, and Cursor CLI as agent tools.

## Built-in Integrations

These ship with PraisonAI. `--external-agent` and `ExternalAgentsHandler.list_integrations()` return these built-ins **plus** any registered plugins — the set is registry-driven, not fixed. See [Register a custom external agent](/docs/features/external-cli-integrations#register-a-custom-external-agent).

| Integration     | CLI Command    | Features                                              |
| --------------- | -------------- | ----------------------------------------------------- |
| **Claude Code** | `claude`       | SDK support, session continuation, tool restrictions  |
| **Gemini CLI**  | `gemini`       | Model selection, multi-directory context, usage stats |
| **Codex CLI**   | `codex`        | Full auto mode, sandbox modes, structured output      |
| **Cursor CLI**  | `cursor-agent` | Force mode, session resume, streaming                 |

## Installation

The integrations are included with PraisonAI:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
pip install praisonai
```

You'll also need to install the respective CLI tools:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Claude Code
curl -fsSL https://claude.ai/install.sh | bash

# Gemini CLI
npm install -g @anthropic-ai/gemini-cli

# Codex CLI
npm install -g @openai/codex

# Cursor CLI
# Download from cursor.com
```

## Quick Start

### Python API

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.integrations import (
    ClaudeCodeIntegration,
    GeminiCLIIntegration,
    CodexCLIIntegration,
    CursorCLIIntegration,
    get_available_integrations
)

# Check which integrations are available
availability = get_available_integrations()
print(availability)
# {'claude': True, 'gemini': True, 'codex': False, 'cursor': True}

# Create an integration
claude = ClaudeCodeIntegration(workspace="/path/to/project")

# Execute a coding task
result = await claude.execute("Refactor the auth module")
print(result)
```

### CLI Usage

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Use external agents from the command line
praisonai "Refactor the code" --external-agent claude
praisonai "Analyze codebase" --external-agent gemini
praisonai "Fix bugs" --external-agent codex
praisonai "Add tests" --external-agent cursor
```

### As Agent Tools

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai import Agent
from praisonai.integrations import ClaudeCodeIntegration

# Create integration
claude = ClaudeCodeIntegration(workspace="/path/to/project")

# Get tool
tool = claude.as_tool()

# Use with agent
agent = Agent(
    name="Code Assistant",
    role="Software Developer",
    goal="Help with coding tasks",
    tools=[tool]
)

result = agent.start("Refactor the authentication module")
```

### As a native async agent tool

Preferred when the agent runs on `agent.astart(...)` (or any async entrypoint) — the tool is awaited directly on the running loop with no thread hop.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent
from praisonai.integrations import ClaudeCodeIntegration

claude = ClaudeCodeIntegration(workspace="/path/to/project")

agent = Agent(
    name="Code Assistant",
    role="Software Developer",
    goal="Help with coding tasks",
    tools=[claude.as_async_tool()],   # registers as `claude_atool`
)

await agent.astart("Refactor the authentication module")
```

`as_async_tool()` was added in PraisonAI PR #4022; `as_tool()` still works and is now also safe to call from inside an async agent runtime.

## CLI Usage: Manager Delegation vs Direct Proxy

PraisonAI now offers two modes for external CLI integration, balancing power and simplicity.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Manager as Manager Agent
    participant CLI as External CLI Tool
    participant User2 as User (Direct)
    participant CLI2 as External CLI Tool (Direct)
    
    Note over User,CLI: Manager Delegation (Default)
    User->>Manager: "Refactor auth.py"
    Manager->>CLI: Call claude_tool
    CLI-->>Manager: Result
    Manager-->>User: Aggregated response
    
    Note over User2,CLI2: Direct Proxy (--external-agent-direct)
    User2->>CLI2: "Refactor auth.py"
    CLI2-->>User2: Direct result
    
    classDef user fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef manager fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef cli fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef result fill:#10B981,stroke:#7C90A0,color:#fff
    
    class User,User2 user
    class Manager manager
    class CLI,CLI2 cli
```

### Manager Delegation (Default)

When using `--external-agent`, a manager Agent wraps the external CLI as a subagent tool, providing reasoning and planning capabilities.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent
from praisonai.integrations import ClaudeCodeIntegration

claude = ClaudeCodeIntegration(workspace=".")
manager = Agent(
    name="Manager",
    instructions="Delegate coding tasks to claude_tool.",
    tools=[claude.as_tool()],
    llm="gpt-4o-mini",
)
manager.start("Refactor the auth module")
```

**When to use manager delegation:**

* Multi-step tasks requiring planning
* Need reasoning across multiple tools
* Want aggregated responses
* Complex workflows with decision-making

**Manager LLM:** Defaults to `gpt-4o-mini`, configurable via `--llm` or `MODEL_NAME` environment variable.

### Direct Proxy (Escape Hatch)

Use `--external-agent-direct` for pass-through behavior — fastest execution with no manager overhead.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Manager delegation (new default)
praisonai "Say hi in 5 words" --external-agent claude

# Direct proxy (escape hatch)  
praisonai "Say hi in 5 words" --external-agent claude --external-agent-direct
```

**When to use direct proxy:**

* Single-shot calls
* Scripting scenarios
* Fastest execution needed
* No manager LLM overhead wanted

## Environment Variables

Set the appropriate API keys for each integration:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Claude Code
export ANTHROPIC_API_KEY=your-key
# or
export CLAUDE_API_KEY=your-key

# Gemini CLI
export GEMINI_API_KEY=your-key
# or
export GOOGLE_API_KEY=your-key

# Cursor CLI
export CURSOR_API_KEY=your-key

# OpenAI (for Codex)
export OPENAI_API_KEY=your-key
```

## ExternalAgentsHandler

The `ExternalAgentsHandler` provides a unified interface for managing external integrations:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.cli.features import ExternalAgentsHandler

handler = ExternalAgentsHandler()

# List available integrations — built-ins plus any registered plugins
integrations = handler.list_integrations()
print(integrations)  # ['claude', 'gemini', 'codex', 'cursor']
# After registering an "aider" plugin:
# ['claude', 'gemini', 'codex', 'cursor', 'aider']

# Check availability
availability = handler.check_availability()
print(availability)
# {'claude': True, 'gemini': True, 'codex': False, 'cursor': True}

# Get a specific integration
claude = handler.get_integration("claude", workspace="/project")
```

On a mixed-version install — a newer `praisonai-code` against a `praisonai` wrapper predating `external_agent_catalog` — `check_dependencies()` returns `(False, "…too old…")` instead of passing and then yielding an empty catalog:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
ok, reason = handler.check_dependencies()
# (False, "your installed 'praisonai' wrapper is too old for --external-agent ...")
```

Three states to tell apart:

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q1{praisonai wrapper installed?} -->|No| Standalone[Empty catalog<br/>standalone still works]
    Q1 -->|Yes| Q2{Has external_agent_catalog?}
    Q2 -->|No| Old[❌ 'wrapper is too old'<br/>pip install -U praisonai]
    Q2 -->|Yes| OK[✅ Full catalog]

    classDef q fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef bad fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef ok fill:#10B981,stroke:#7C90A0,color:#fff

    class Q1,Q2 q
    class Old bad
    class Standalone,OK ok
```

## Performance

All integrations are designed with zero performance impact:

| Metric                      | Result                 |
| --------------------------- | ---------------------- |
| Import time                 | \< 1ms                 |
| Availability check (first)  | \~1ms                  |
| Availability check (cached) | \~0ms                  |
| Memory overhead             | Minimal (lazy loading) |

### Lazy Loading

Integrations are only imported when used:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# This does NOT import any integration classes
from praisonai.integrations import get_available_integrations

# This imports only ClaudeCodeIntegration
from praisonai.integrations import ClaudeCodeIntegration
```

### Availability Caching

CLI availability checks are cached at the class level:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.integrations import ClaudeCodeIntegration

claude1 = ClaudeCodeIntegration()
claude2 = ClaudeCodeIntegration()

# Both use the same cached availability check
print(claude1.is_available)  # Checks filesystem
print(claude2.is_available)  # Uses cached result
```

## Streaming

All integrations support streaming output:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.integrations import ClaudeCodeIntegration

claude = ClaudeCodeIntegration()

async for event in claude.stream("Add error handling to main.py"):
    print(event)
    # {'type': 'assistant', 'content': '...'}
    # {'type': 'tool_use', 'name': 'Write', ...}
    # {'type': 'result', 'content': '...'}
```

## Error Handling

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.integrations import ClaudeCodeIntegration

claude = ClaudeCodeIntegration(timeout=60)

try:
    result = await claude.execute("Complex refactoring task")
except TimeoutError:
    print("Task timed out")
except Exception as e:
    print(f"Error: {e}")
```

The CLI execution path distinguishes an unknown name (`ValueError`) from a version-skewed install (`RuntimeError`):

| Situation                         | Raised / shown                                                                         | Fix                                                    |
| --------------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| Name not registered               | `ValueError: Unknown integration: <name>. Available: [...]`                            | Check the name or install the plugin                   |
| `praisonai` wrapper too old       | `RuntimeError: your installed 'praisonai' wrapper is too old for --external-agent ...` | `pip install -U praisonai`                             |
| `praisonai` wrapper not installed | Empty catalog, `ValueError: Unknown integration`                                       | Install `praisonai` if you need registry-backed agents |

## Using from PraisonAI UI

<Tip>
  Instead of writing Python code, you can enable external agents directly from any PraisonAI UI by flipping toggles in the interface. See [External Agents in UI](/docs/features/external-agents-ui) for complete documentation on UI-based external agent management.
</Tip>

## Next Steps

<CardGroup cols={2}>
  <Card title="Claude Code" icon="message-bot" href="/docs/code/claude-code">
    Detailed Claude Code integration guide
  </Card>

  <Card title="Gemini CLI" icon="google" href="/docs/code/gemini-cli">
    Detailed Gemini CLI integration guide
  </Card>

  <Card title="Codex CLI" icon="openai" href="/docs/code/codex-cli">
    Detailed Codex CLI integration guide
  </Card>

  <Card title="Cursor CLI" icon="cursor" href="/docs/code/cursor-cli">
    Detailed Cursor CLI integration guide
  </Card>
</CardGroup>
