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

> ## Agent Instructions
> Phaseo Gateway base URL: https://api.phaseo.app/v1. Send `Authorization: Bearer $PHASEO_API_KEY` with every request.
> Model IDs look like `provider/model`, for example `openai/gpt-6-astra`. Do not guess IDs: list them with `GET /v1/models` or check https://phaseo.app/models. `phaseo/free` routes to an available free model and needs no wallet balance.
> For new text integrations prefer `POST /v1/responses`. `POST /v1/chat/completions` (OpenAI format) and `POST /v1/messages` (Anthropic format) suit existing code.
> The full API contract is https://phaseo.app/docs/openapi/v1/openapi.yaml. Official SDKs: `@phaseo/sdk` (TypeScript) and `phaseo` (Python), plus Go, C#, PHP, Ruby and Rust.
> Search these docs over MCP at https://phaseo.app/docs/mcp, and install Phaseo skills with `npx skills add https://phaseo.app/docs`. If a page is wrong or out of date, report it with the MCP `submit_feedback` tool.
> Manage Phaseo accounts with the `phaseo` CLI (`npm install -g @phaseo/cli`, then `phaseo login` or `phaseo login --device-code`), the `/v1` Management API or the MCP server at `https://mcp.phaseo.app/mcp?access=manage`. Do not send users to the dashboard for account tasks. A person is still needed for sign-up, approving a sign-in, paying the first top-up on the checkout link that `phaseo credits add` returns when no card is saved, confirming each saved-card top-up from the emailed link, and account security (password, MFA, passkeys). Create API keys with `phaseo keys create --name <name> --json`; never guess one. Credit top-ups need `phaseo login --scopes billing:write` first. Task map: https://phaseo.app/docs/v1/developers/manage-from-an-agent.md.

# 示例

> 复制针对审批、流式传输和有边界运行的 Agent SDK 模式，或者从完整的示例方案开始。

从一个智能体、一两个确定性的工具，以及围绕副作用的审批开始。下面的代码片段假定 `client` 中有一个网关智能体客户端（Go 中还有一个 `ctx`）。它们只是示意：`deployments`、`store`、`search` 和 `fetchPage` 代表你自己的代码。

## 需要审批的部署

部署工具会让运行暂停，直到有人批准这个确切的调用。保存已暂停的结果，把待处理调用展示给审核人，然后带着决定继续运行。

```typescript TypeScript theme={null}
const deploy = defineTool({
  id: "deploy",
  requireApproval: ({ environment }) => environment === "production",
  async execute(input: { environment: string }) {
    return deployments.deploy(input.environment);
  },
});

const agent = createAgent({ id: "release-agent", model: "openai/gpt-6-astra", tools: [deploy] });

let result = await agent.run({ input: "Ship release 42 to production", client });
if (result.run.status === "waiting_for_human") {
  await store.save(result); // 把 result.run.pause.pendingToolCalls 展示给审核人

  // 之后，在审核人批准后：
  const callId = result.run.pause!.pendingToolCalls[0].call.id;
  result = await agent.continueRun({ run: result, client, approvals: [{ toolCallId: callId }] });
}
```

```python Python theme={null}
from phaseo_agent import AgentTool, AgentToolDecision, create_agent, define_tool

deploy = define_tool(AgentTool(
    id="deploy",
    description="Deploy the selected release",
    parameters={"type": "object", "properties": {"environment": {"type": "string"}}},
    require_approval=True,
    execute=lambda tool_input, runtime: deployments.deploy(tool_input["environment"]),
))

agent = create_agent({"id": "release-agent", "model": "openai/gpt-6-astra", "tools": [deploy]})

result = agent.run(input="Ship release 42", client=client)
if result.run.status == "waiting_for_human":
    store.save(result)  # 把 result.run.pause.pending_tool_calls 展示给审核人

    # 之后，在审核人批准后：
    call_id = result.run.pause.pending_tool_calls[0].call.id
    result = agent.continue_run(run=result, client=client, approvals=[AgentToolDecision(call_id)])
```

```go Go theme={null}
deploy := phaseoagent.DefineTool(phaseoagent.Tool{
  ID:              "deploy",
  Description:     "Deploy the selected release",
  RequireApproval: true,
  Execute: func(input any, runtime phaseoagent.RuntimeContext) (any, error) {
    return deploymentService.Deploy(input)
  },
})

agent := phaseoagent.CreateAgent(phaseoagent.AgentDefinition{
  ID: "release-agent", Model: "openai/gpt-6-astra", Tools: []phaseoagent.Tool{deploy},
})

result, err := agent.Run(ctx, phaseoagent.RunOptions{Input: "Ship release 42", Client: client})
if err == nil && result.Run.Status == "waiting_for_human" {
  store.Save(result) // 把 result.Run.Pause.PendingToolCalls 展示给审核人

  // 之后，在审核人批准后：
  callID := result.Run.Pause.PendingToolCalls[0].Call.ID
  result, err = agent.Continue(ctx, phaseoagent.ContinueOptions{
    Run: result, Client: client,
    Approvals: []phaseoagent.ToolDecision{{ToolCallID: callID}},
  })
}
```

```csharp C# theme={null}
var deploy = AgentSdk.DefineTool(new Tool(
    "deploy",
    async (input, runtime) => await deployments.DeployAsync(input, runtime.CancellationToken),
    "Deploy the selected release")
{
    RequireApproval = true,
});

var agent = AgentSdk.CreateAgent(new AgentDefinition
{
    Id = "release-agent", Model = "openai/gpt-6-astra", Tools = new[] { deploy },
});

var result = await agent.Run(new RunOptions { Input = "Ship release 42", Client = client });
if (result.Run.Status == "waiting_for_human")
{
    await store.SaveAsync(result); // 把 result.Run.Pause.PendingToolCalls 展示给审核人

    // 之后，在审核人批准后：
    var callId = result.Run.Pause!.PendingToolCalls![0].Call.Id;
    result = await agent.ContinueRun(new ContinueOptions
    {
        Run = result, Client = client, Approvals = new[] { new ToolDecision(callId) },
    });
}
```

```php PHP theme={null}
use Phaseo\AgentSdk\{AgentDefinition, AgentSdk, Tool, ToolDecision};

$deploy = AgentSdk::defineTool(new Tool(
    id: "deploy",
    execute: fn (array $input, $runtime) => $deployments->deploy($input),
    description: "Deploy the selected release",
    requireApproval: true,
));

$agent = AgentSdk::createAgent(new AgentDefinition(
    id: "release-agent", model: "openai/gpt-6-astra", tools: [$deploy],
));

$result = $agent->run(input: "Ship release 42", client: $client);
if ($result->run->status === "waiting_for_human") {
    $store->save($result); // 把 $result->run->pause->pendingToolCalls 展示给审核人

    // 之后，在审核人批准后：
    $callId = $result->run->pause->pendingToolCalls[0]->call->id;
    $result = $agent->continueRun(run: $result, client: $client, approvals: [new ToolDecision($callId)]);
}
```

```ruby Ruby theme={null}
deploy = PhaseoAgentSdk.define_tool(
  PhaseoAgentSdk::Tool.new(
    id: "deploy",
    description: "Deploy the selected release",
    require_approval: true,
    execute: ->(input, runtime) { deployments.deploy(input) }
  )
)

agent = PhaseoAgentSdk.create_agent(id: "release-agent", model: "openai/gpt-6-astra", tools: [deploy])

result = agent.run(input: "Ship release 42", client: client)
if result.run.status == "waiting_for_human"
  store.save(result) # 把 result.run.pause.pending_tool_calls 展示给审核人

  # 之后，在审核人批准后：
  call_id = result.run.pause.pending_tool_calls.first.call.id
  result = agent.continue_run(
    run: result,
    client: client,
    approvals: [PhaseoAgentSdk::ToolDecision.new(tool_call_id: call_id)]
  )
end
```

```java Java theme={null}
var deploy = AgentSdk.defineTool(new AgentSdk.Tool(
    "deploy", (input, context) -> deployments.deploy(input), "Deploy the selected release",
    Map.of("type", "object"), null,
    null, null, null,
    true, null,             // requireApproval
    null, null, "fail-run"));

var agent = AgentSdk.createAgent(new AgentSdk.AgentDefinition(
    "release-agent", "openai/gpt-6-astra", null, null, List.of(deploy), 12, null, null, null, null));

var result = agent.run(new AgentSdk.RunOptions(
    "Ship release 42", client, null, null, null, null, null, null, null, null));

if (result.run().status().equals("waiting_for_human")) {
    store.save(result); // 把 result.run().pause().pendingToolCalls() 展示给审核人

    // 之后，在审核人批准后：
    var callId = result.run().pause().pendingToolCalls().get(0).call().id();
    result = agent.continueRun(new AgentSdk.ContinueOptions(
        result, client, null, null, null, null, null, null, null, null, null,
        List.of(new AgentSdk.ToolDecision(callId)), List.of(), List.of()));
}
```

```rust Rust theme={null}
use phaseo_agent::{
    create_agent, AgentDefinition, ContinueOptions, RunOptions, Tool, ToolDecision,
};
use serde_json::json;

let deploy = Tool::new(
    "deploy",
    "Deploy the selected release",
    json!({ "type": "object", "properties": { "environment": { "type": "string" } } }),
    |input, _context| Ok(json!({ "environment": input["environment"], "deployed": true })),
)
.require_approval();

let agent = create_agent(AgentDefinition::new("release-agent", "openai/gpt-6-astra").tool(deploy));

let mut result = agent.run(&mut client, RunOptions::new("Ship release 42"))?;
if result.run.status == "waiting_for_human" {
    store.save(&result)?; // 把待处理的工具调用展示给审核人

    // 之后，在审核人批准后：
    let call_id = result.run.pause.as_ref().unwrap().pending_tool_calls[0].call.id.clone();
    let mut options = ContinueOptions::new(result);
    options.approvals = vec![ToolDecision { tool_call_id: call_id, reason: None }];
    result = agent.continue_run(&mut client, options)?;
}
```

[状态与审批](https://phaseo.app/docs/zh-Hans/v1/sdk-reference/agent/state-and-approval.md)介绍了拒绝、手动工具输出和保存运行。

## 流式输出到终端

```typescript TypeScript theme={null}
const stream = agent.stream({ input, client });

for await (const delta of stream.getTextStream()) {
  process.stdout.write(delta);
}

const completed = await stream.getResult();
```

```python Python theme={null}
stream = agent.stream(input="Research this topic", client=client)

for delta in stream.text_stream():
    print(delta, end="", flush=True)

completed = stream.result()
```

```go Go theme={null}
stream := agent.Stream(ctx, phaseoagent.RunOptions{Input: prompt, Client: client})
for delta := range stream.Text() {
  fmt.Print(delta)
}
result, err := stream.Result()
```

```csharp C# theme={null}
var stream = agent.Stream(new RunOptions { Input = prompt, Client = client });
await foreach (var delta in stream.TextStream()) Console.Write(delta);
var completed = await stream.GetResult();
```

```php PHP theme={null}
$stream = $agent->stream(input: $prompt, client: $client);
foreach ($stream->textStream() as $delta) { echo $delta; }
$result = $stream->getResult();
```

```ruby Ruby theme={null}
stream = agent.stream(input: prompt, client: client)
stream.text_stream.each { |delta| print delta }
result = stream.result
```

```java Java theme={null}
// Java 的 textStream() 只在运行结束后才会填充，所以从 onEvent 中打印增量
var options = new AgentSdk.RunOptions(prompt, client, null, null, null, null, null, null,
    event -> { if (event.type().equals("response.output_text.delta")) System.out.print(event.details().get("delta")); },
    null);
var completed = agent.stream(options).getResult();
```

Rust `0.2` 没有流式传输；`run` 在运行结束后才返回。参见[流式传输](https://phaseo.app/docs/zh-Hans/v1/sdk-reference/agent/streaming.md)。

## 限制自主研究

组合多个上限；最先触发的那个会以 `stopped` 状态和类似 `max_cost:1` 的停止原因结束运行。

```typescript TypeScript theme={null}
import { maxCost, maxDuration, maxTokensUsed, stepCountIs } from "@phaseo/agent-sdk";

const agent = createAgent({
  id: "researcher",
  model: "openai/gpt-6-astra",
  tools: [search, fetchPage],
  maxSteps: 25,
  stopWhen: [
    stepCountIs(20),
    maxTokensUsed(100_000),
    maxCost(1),
    maxDuration(300_000),
  ],
});
```

```python Python theme={null}
from phaseo_agent import create_agent, max_cost, max_duration, max_tokens_used, step_count_is

agent = create_agent({
    "id": "researcher",
    "model": "openai/gpt-6-astra",
    "tools": [search, fetch_page],
    "max_steps": 25,
    "stop_when": [
        step_count_is(20),
        max_tokens_used(100_000),
        max_cost(1),
        max_duration(300_000),
    ],
})
```

```go Go theme={null}
agent := phaseoagent.CreateAgent(phaseoagent.AgentDefinition{
  ID:    "researcher",
  Model: "openai/gpt-6-astra",
  Tools: []phaseoagent.Tool{search, fetchPage},
  StopWhen: []phaseoagent.StopCondition{
    phaseoagent.StepCountIs(20),
    phaseoagent.MaxTokensUsed(100_000),
    phaseoagent.MaxCost(1.00),
    phaseoagent.MaxDuration(5 * time.Minute),
  },
  MaxSteps: 25,
})
```

```csharp C# theme={null}
var agent = AgentSdk.CreateAgent(new AgentDefinition
{
    Id = "researcher",
    Model = "openai/gpt-6-astra",
    Tools = new[] { search, fetchPage },
    StopWhen = new[]
    {
        AgentSdk.StepCountIs(20),
        AgentSdk.MaxTokensUsed(100_000),
        AgentSdk.MaxCost(1.00),
        AgentSdk.MaxDuration(TimeSpan.FromMinutes(5)),
    },
    MaxSteps = 25,
});
```

```php PHP theme={null}
$agent = AgentSdk::createAgent(new AgentDefinition(
    id: "researcher",
    model: "openai/gpt-6-astra",
    tools: [$search, $fetchPage],
    maxSteps: 25,
    stopWhen: [
        AgentSdk::stepCountIs(20),
        AgentSdk::maxTokensUsed(100000),
        AgentSdk::maxCost(1.00),
        AgentSdk::maxDuration(300000),
    ],
));
```

```ruby Ruby theme={null}
agent = PhaseoAgentSdk.create_agent(
  id: "researcher",
  model: "openai/gpt-6-astra",
  tools: [search, fetch_page],
  max_steps: 25,
  stop_when: [
    PhaseoAgentSdk.step_count_is(20),
    PhaseoAgentSdk.max_tokens_used(100_000),
    PhaseoAgentSdk.max_cost(1.00),
    PhaseoAgentSdk.max_duration(300_000)
  ]
)
```

```java Java theme={null}
var agent = AgentSdk.createAgent(new AgentSdk.AgentDefinition(
    "researcher", "openai/gpt-6-astra", null, null, List.of(search, fetchPage), 25,
    null, null, null, null,
    List.of(
        AgentSdk.stepCountIs(20),
        AgentSdk.maxTokensUsed(100_000),
        AgentSdk.maxCost(1.00),
        AgentSdk.maxDuration(Duration.ofMinutes(5))),
    null, null));
```

```rust Rust theme={null}
// Rust 0.2 没有停止条件；改为限制模型轮次。
let agent = create_agent(
    AgentDefinition::new("researcher", "openai/gpt-6-astra")
        .tool(search)
        .tool(fetch_page)
        .max_steps(20),
);
```

停止原因中数字的格式取决于语言：Go、C# 和 PHP 中为 `max_cost:1`，Ruby 和 Java 中为 `max_cost:1.0`。在 Rust 中，达到步数上限会以 `stopped` 结束运行，原因为 `max_steps:20`。参见[停止条件](https://phaseo.app/docs/zh-Hans/v1/sdk-reference/agent/stop-conditions.md)。

## 为常见产品组合功能

| 产品 | 组合 |
| - | - |
| 结构化提取 | [输出校验](https://phaseo.app/docs/zh-Hans/v1/sdk-reference/agent/run-controls.md#validate-the-final-output)、网关客户端上的严格响应格式、有上限的重试 |
| 支持分诊 | 用于路由的 `preset`、查询类[工具](https://phaseo.app/docs/zh-Hans/v1/sdk-reference/agent/tools.md)、用于最终分类的结构化输出 |
| 研究简报 | 通过网关客户端的网关工具进行托管搜索、[流式](https://phaseo.app/docs/zh-Hans/v1/sdk-reference/agent/streaming.md)文本、[停止条件](https://phaseo.app/docs/zh-Hans/v1/sdk-reference/agent/stop-conditions.md) |
| 代码审查或编程助手 | 文件工具、进度事件、修改前的[审批](https://phaseo.app/docs/zh-Hans/v1/sdk-reference/agent/state-and-approval.md) |
| 运维手册 | 状态工具、手动升级处理、之后继续的已保存运行 |

TypeScript 包在它的 `examples/` 文件夹中提供了其中四种的完整版本：`research-brief-agent.ts`、`support-triage-agent.ts`、`coding-review-agent.ts` 和 `parallel-tool-agent.ts`（独立的本地工具并发运行）。

## 跟着示例方案走一遍

> [card] [持久智能体循环](https://phaseo.app/docs/zh-Hans/v1/cookbook/agent-sdk-durable-loop.md)
>
> 持久化返回的运行，并在之后的请求中继续它。

> [card] [研究简报](https://phaseo.app/docs/zh-Hans/v1/cookbook/agent-sdk-research-brief.md)
>
> 把智能体与有依据的网页研究结合起来。

> [card] [支持分诊](https://phaseo.app/docs/zh-Hans/v1/cookbook/agent-sdk-support-triage.md)
>
> 把路由和提示词默认值放在托管预设中。

> [card] [代码审查](https://phaseo.app/docs/zh-Hans/v1/cookbook/agent-sdk-coding-review.md)
>
> 把专注的本地工具接入编程工作流。

> [card] [并行工具](https://phaseo.app/docs/zh-Hans/v1/cookbook/agent-sdk-parallel-tools.md)
>
> 展开相互独立的工具调用，而不改变结果顺序。

> [card] [结构化提取（Python）](https://phaseo.app/docs/zh-Hans/v1/cookbook/agent-sdk-python-structured-extraction.md)
>
> 用 Python Agent SDK 提取结构化 JSON。

> [card] [运维手册（Go）](https://phaseo.app/docs/zh-Hans/v1/cookbook/agent-sdk-go-ops-runbook.md)
>
> 用 Go 构建运维手册智能体。

> [card] [工单分诊（C#）](https://phaseo.app/docs/zh-Hans/v1/cookbook/agent-sdk-csharp-ticket-triage.md)
>
> 用 C# Agent SDK 分诊工单。

> [card] [内容审核（PHP）](https://phaseo.app/docs/zh-Hans/v1/cookbook/agent-sdk-php-content-review.md)
>
> 用 PHP Agent SDK 审核 CMS 内容。

> [card] [笔记总结（Ruby）](https://phaseo.app/docs/zh-Hans/v1/cookbook/agent-sdk-ruby-rag-notes.md)
>
> 用 Ruby Agent SDK 总结内部笔记。

前五个示例方案使用 TypeScript。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.