> For the complete documentation index, see [llms.txt](https://docs.neuron-ai.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.neuron-ai.dev/neuron-v3-zh/zhi-neng-ti/agent.md).

# 智能体

借助内置记忆和工具使用，轻松实现 LLM 交互。

### 介绍

你可以通过扩展以下内容来创建你的代理： `NeuronAI\Agent\Agent` 类，从而继承框架的主要功能并创建完全可用的代理。

这个类会自动为你管理一些机制，例如记忆、工具和函数调用。我们将在后续章节中更详细地介绍这些方面。

我们强烈建议扩展 Agent 类，而不是使用以下方式创建代理： [流式定义](#fluent-agent-definition)。这种策略让你更容易为代理添加自定义方法和行为，同时也提高了可移植性，因为所有组件都封装在一个单独的实体中，你可以在应用中的任何地方运行它，甚至将其作为独立的 composer 包发布。

让我们开始创建一个用于总结 YouTube 视频的 AI 代理。我们先创建 `YouTubeAgent` 类：

{% tabs %}
{% tab title="Unix" %}

```bash
vendor/bin/neuron make:agent App\\Neuron\\YouTubeAgent
```

{% endtab %}

{% tab title="Windows" %}

```powershell
.\vendor\bin\neuron make:agent App\Neuron\YouTubeAgent
```

{% endtab %}
{% endtabs %}

该命令将创建如下类：

```php
<?php

namespace App\Neuron;

use NeuronAI\Agent\Agent;
use NeuronAI\Agent\SystemPrompt;
use NeuronAI\Providers\AIProviderInterface;

class YouTubeAgent extends Agent
{
    protected function provider(): AIProviderInterface
    {
        // 返回 Anthropic、OpenAI、Gemini、Ollama 等的实例...
    }
    
    protected function instructions(): string
    {
        return "你是一个使用 Neuron AI 框架创建的友好 AI 代理。";
    }
    
    /**
     * @return \NeuronAI\Tools\ToolInterface[]
     */
    protected function tools(): array
    {
        return [];
    }
}
```

### 监控与调试

你使用 Neuron 构建的许多应用都会包含多个步骤以及多次 LLM 调用。随着这些应用变得越来越复杂，能够检查你的 agent 系统内部究竟发生了什么就变得至关重要。实现这一点的最佳方式是使用 [Inspector](https://inspector.dev/).

{% embed url="<https://docs.inspector.dev/guides/neuron-ai>" %}

### AI 提供商

最小实现要求你分配一个 AI 提供商，它将成为代理的语言和推理引擎。

唯一需要实现的方法是 `provider()` ，它返回你要使用的提供商实例。我们假设它是 Anthropic。

```php
<?php

namespace App\Neuron;

use NeuronAI\Agent\Agent;
use NeuronAI\Agent\SystemPrompt;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\Providers\Anthropic\Anthropic;

class YouTubeAgent extends Agent
{
    protected function provider(): AIProviderInterface
    {
        // 返回 Anthropic、OpenAI、Gemini、Ollama 等的实例...
        return new Anthropic(
            key: 'ANTHROPIC_API_KEY',
            model: 'ANTHROPIC_MODEL',
        );
    }
    
    protected function instructions(): string
    {
        return "你是一个使用 Neuron AI 框架创建的友好 AI 代理。";
    }
    
    /**
     * @return \NeuronAI\Tools\ToolInterface[]
     */
    protected function tools(): array
    {
        return [];
    }
}
```

如果你愿意，也可以使用其他提供商，比如 OpenAI、Gemini，或者如果你想在本地运行模型，也可以使用 Ollama。查看 [受支持的提供商](/neuron-v3-zh/ti-gong-shang/ai-provider.md).

### 系统指令

第二个重要的构建块是系统指令。系统指令用于指导 AI 按照我们想要实现的任务来行动。它们是每次交互都会发送给 LLM 的固定指令。

这就是它们由内部方法定义并封装在代理实体中的原因。让我们实现 `instructions()` 方法：

```php
<?php

namespace App\Neuron;

use NeuronAI\Agent\Agent;
use NeuronAI\Agent\SystemPrompt;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\Providers\Anthropic\Anthropic;

class YouTubeAgent extends Agent
{
    protected function provider(): AIProviderInterface
    {
        // 返回一个 AI 提供商实例（Anthropic、OpenAI、Ollama、Gemini 等）
        return new Anthropic(
            key: 'ANTHROPIC_API_KEY',
            model: 'ANTHROPIC_MODEL',
        );
    }
    
    protected function instructions(): string
    {
        return <<<TEXT
            你是一个专门撰写 YouTube 视频摘要的 AI 代理。
            获取 YouTube 视频的 URL，或者请用户提供一个。
            使用你可用的工具来获取视频的转录文本。
            写一段摘要，不要使用列表。只使用流畅的文本。
            在摘要之后，添加一个由三句话组成的列表，作为该视频最重要的三个要点。
        TEXT;
    }
    
    /**
     * @return \NeuronAI\Tools\ToolInterface[]
     */
    protected function tools(): array
    {
        return [];
    }
}
```

### 与代理对话

我们已经准备好测试代理如何根据新指令响应我们的消息。

```php
use NeuronAI\Chat\Messages\UserMessage;

$message = YouTubeAgent::make()
    ->chat(new UserMessage("你是谁？"))
    ->getMessage();
    
echo $message->getContent();
// 嗨，我是一个专门总结 YouTube 视频的友好 AI 代理！
// 你能给我一个你想要快速摘要的 YouTube 视频 URL 吗？
```

### 代理状态

由于 Agent 是 Workflow 的扩展，因此你不需要通过 `getMessage()` 方法来获取模型的最后响应，而是可以直接运行代理工作流，并将原始代理状态作为返回值。代理状态包含额外信息，可帮助你检查代理执行期间发生了什么。

```php
$state = MyAgent::make()
    ->chat(new UserMessage("你是谁？"))
    ->run();

// $state 是 NeuronAI\Agent\AgentState 类的实例
$state->getMessage();
```

#### 步骤

调用 `getMessage()` 方法时，你只能获取模型为回答你的提示而生成的最后一条消息。但在内部，代理在给出最终答案之前可能会执行多次工具调用迭代。

代理状态会保存当前执行周期中代理与提供商之间所有消息的列表，而不仅仅是最终答案。因此，你可以通过代理状态上的 `getSteps()` 方法访问消息列表：

```php
$state = MyAgent::make()
    ->chat(new UserMessage("你是谁？"))
    ->run();

// 访问执行期间的步骤列表
foreach($state->getSteps() as $message) {
    echo "- ".$message::class."\n";
}

// 最终答案
echo $state->getMessage()->getContent();
```

#### 工具运行

如果代理在执行过程中决定使用工具，代理状态会跟踪工具运行次数，以便在以下情况下停止执行： [maxRuns](/neuron-v3-zh/zhi-neng-ti/tools.md#max-runs) 达到限制。你可以访问这个映射：

```php
$state = MyAgent::make()
    ->chat(new UserMessage("你是谁？"))
    ->run();

// 访问工具运行映射
foreach($state->getToolRuns() as $toolName => $runs) {
    echo "- 工具 {$toolName} 被使用了 {$runs} 次\n";
}
```

### 消息

代理始终接受输入作为一个 `消息` 类，并返回 Message 实例。

正如你在上面的示例中看到的，我们向代理发送了一个 `UserMessage` 实例，并检索到回复消息，它将是一个 `AssistantMessage` 实例。助理消息和用户消息的列表构成一个聊天。

我们稍后会进一步了解 [ChatHistory](/neuron-v3-zh/zhi-neng-ti/chat-history-and-memory.md) ，但重要的是要知道，代理输入和输出的统一接口是 `消息` 对象。

<a href="/neuron-v3-zh/zhi-neng-ti/messages.md" class="button primary" data-icon="arrow-right-long">了解更多关于消息的信息</a>

### 流式代理定义

除了单类封装之外，你还可以使用流式方法链在内联中指导代理：

```php
$agent = Agent::make()
    ->setAiProvider(
        new Anthropic(
            key: 'ANTHROPIC_API_KEY',
            model: 'ANTHROPIC_MODEL',
        )
    )
    ->setInstructions(
        "新的系统指令..."
    )
    ->addTool([...]);
    
$message = $agent->chat(new UserMessage(...))->getMessage();
echo $message->gentContent();
```
