可观测性与使用情况
AI translation, not an official translation. Refer to the original for technical details.
On this page
完整文档索引请参见 llms.txt。在页面 URL 后附加
.md可获取文档页面的 Markdown 版本。
追踪实时 Agent 活动、检查已完成的工作,以及查看详细的轮次追踪:
- 您可以在 Platform 控制台中查看会话日志。
- 您可以通过事件流和已保存的历史记录跟踪会话进展。
- 您可以检查轮次并识别已委托的命令执行。
- 您可以检查根 Agent 和子 Agent 轮次的已记录 Token 用量。
在控制台中查看会话
前往 platform.openai.com/logs?api=agents 并打开 Agents 标签页。
通过 ID 搜索会话,以检查其轮次、工具调用和子 Agent。
使用追踪指南在控制台中检查已记录的模型响应、工具调用和子 Agent 活动。追踪检索与外部追踪导出器不属于公测 API 的范围。
跟踪事件流并检查会话历史
每个会话都提供一个事件流,实时显示 Agent 正在执行的操作。设置 OPENAI_API_KEY 并将以下示例中的示意性会话 ID 替换为您保存的会话 ID:
跟踪实时会话事件
// Replace the illustrative IDs and URLs below with your own resource values.
import OpenAI from "openai";
const client = new OpenAI();
const events = await client.beta.agents.sessions.events.stream("sess_123");
try {
for await (const event of events) {
if (
[
"agent.session.turn.failed",
"agent.session.turn.cancelled",
"agent.session.failed",
"agent.session.environment.failed",
"error",
].includes(event.type)
) {
throw new Error(`Agent lifecycle failure: ${event.type}`);
}
console.log(JSON.stringify(event));
}
} finally {
events.controller.abort();
}
# Replace the illustrative IDs and URLs below with your own resource values.
from openai import OpenAI
client = OpenAI()
session_id = "sess_123"
with client.beta.agents.sessions.events.stream(session_id) as events:
for event in events:
if event.type in {
"agent.session.turn.failed",
"agent.session.turn.cancelled",
"agent.session.failed",
"agent.session.environment.failed",
"error",
}:
raise RuntimeError(f"Agent lifecycle failure: {event.type}")
print(event.to_json(indent=None))
// Replace the illustrative IDs and URLs below with your own resource values.
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
)
ctx := context.Background()
client := openai.NewClient()
events := client.Beta.Agents.Sessions.Events.StreamStreaming(ctx, "sess_123")
defer events.Close()
if events.Err() != nil {
panic(events.Err())
}
for events.Next() {
event := events.Current()
switch event.Type {
case "agent.session.turn.failed", "agent.session.turn.cancelled", "agent.session.failed", "agent.session.environment.failed", "error":
panic(event.RawJSON())
}
fmt.Println(event.RawJSON())
}
if err := events.Err(); err != nil {
panic(err)
}
// Replace the illustrative IDs and URLs below with your own resource values.
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.http.StreamResponse;
import com.openai.models.beta.agents.AgentSessionEvent;
OpenAIClient client = OpenAIOkHttpClient.fromEnv();
var json = new JsonMapper();
try (StreamResponse<AgentSessionEvent> events =
client.beta().agents().sessions().events().streamStreaming("sess_123")) {
var iterator = events.stream().iterator();
while (iterator.hasNext()) {
var event = iterator.next();
if (event.turnFailed().isPresent()
|| event.turnCancelled().isPresent()
|| event.failed().isPresent()
|| event.environmentFailed().isPresent()
|| event.error().isPresent()) {
throw new IllegalStateException("Agent failed: " + event);
}
System.out.println(json.writeValueAsString(event));
}
}
# Replace the illustrative IDs and URLs below with your own resource values.
require "openai"
require "json"
client = OpenAI::Client.new
events = client.beta.agents.sessions.events.stream_streaming("sess_123")
begin
events.each do |event|
case event.type.to_s
when "agent.session.turn.failed", "agent.session.turn.cancelled", "agent.session.failed", "agent.session.environment.failed", "error"
raise "Agent failed: #{event.to_h}"
end
puts JSON.generate(event.to_h)
end
ensure
events.close
end
curl -N \
-H "OpenAI-Beta: agents=v1" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Accept: text/event-stream" \
"https://api.openai.com/v1/agents/sessions/sess_123/events?stream=true"
事件流在空闲事件期间保持打开状态,以确保不遗漏已排队的工作。按 Ctrl+C 停止监听。
在会话运行时,您将看到如下事件:
agent.session.environment.connected
agent.session.turn.created
agent.session.turn.in_progress
agent.session.turn.item.added
agent.session.turn.output_text.delta
agent.session.turn.completed
agent.session.idle
如需检查已发生的工作,可检索会话的已保存条目:
检查已保存的会话条目
// Replace the illustrative IDs and URLs below with your own resource values.
import OpenAI from "openai";
const client = new OpenAI();
const sessionId = "sess_123";
const items = await client.beta.agents.sessions.items.list(sessionId, {
order: "asc",
limit: 100,
});
console.log(items.data);
# Replace the illustrative IDs and URLs below with your own resource values.
from openai import OpenAI
client = OpenAI()
session_id = "sess_123"
items = client.beta.agents.sessions.items.list(session_id, order="asc", limit=100)
print(items.to_json())
// Replace the illustrative IDs and URLs below with your own resource values.
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
)
ctx := context.Background()
client := openai.NewClient()
result, err := client.Beta.Agents.Sessions.Items.List(ctx,
"sess_123",
openai.BetaAgentSessionItemListParams{
Order: "asc",
Limit: openai.Int(100),
})
if err != nil {
panic(err)
}
fmt.Println(result.Data)
// Replace the illustrative IDs and URLs below with your own resource values.
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.beta.agents.sessions.items.ItemListParams;
OpenAIClient client = OpenAIOkHttpClient.fromEnv();
var result =
client
.beta()
.agents()
.sessions()
.items()
.list(
ItemListParams.builder()
.sessionId("sess_123")
.order(ItemListParams.Order.of("asc"))
.limit(100L)
.build());
System.out.println(result.items());
# Replace the illustrative IDs and URLs below with your own resource values.
require "openai"
client = OpenAI::Client.new
result = client.beta.agents.sessions.items.list(
"sess_123",
order: "asc",
limit: 100
)
puts result.data
curl \
-H "OpenAI-Beta: agents=v1" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
"https://api.openai.com/v1/agents/sessions/sess_123/items?order=asc&limit=100"
检查轮次并识别已委托的命令
会话轮次可通过公开 API 获取。使用命令条目中的 turn_id,结合您保存的会话 ID。cURL 示例需要 jq:
识别已委托的命令执行
// Replace the illustrative IDs and URLs below with your own resource values.
import OpenAI from "openai";
const client = new OpenAI();
const sessionId = "sess_123";
const turns = await client.beta.agents.sessions.turns.list(sessionId, {
limit: 20,
order: "desc",
});
console.log(turns.data);
const turnId = "turn_123";
const turn = await client.beta.agents.sessions.turns.retrieve(turnId, {
session_id: sessionId,
});
console.log(turn.subagent_id);
# Replace the illustrative IDs and URLs below with your own resource values.
from openai import OpenAI
client = OpenAI()
session_id = "sess_123"
turns = client.beta.agents.sessions.turns.list(session_id, limit=20, order="desc")
print(turns.to_json())
turn_id = "turn_123"
turn = client.beta.agents.sessions.turns.retrieve(turn_id, session_id=session_id)
print(turn.subagent_id)
// Replace the illustrative IDs and URLs below with your own resource values.
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
)
ctx := context.Background()
client := openai.NewClient()
result, err := client.Beta.Agents.Sessions.Turns.List(ctx,
"sess_123",
openai.BetaAgentSessionTurnListParams{
Limit: openai.Int(20),
Order: "desc",
})
if err != nil {
panic(err)
}
fmt.Println(result.Data)
turn, err := client.Beta.Agents.Sessions.Turns.Get(ctx,
"sess_123",
"turn_123")
if err != nil {
panic(err)
}
fmt.Println(turn.SubagentID)
// Replace the illustrative IDs and URLs below with your own resource values.
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.beta.agents.sessions.turns.TurnListParams;
import com.openai.models.beta.agents.sessions.turns.TurnRetrieveParams;
OpenAIClient client = OpenAIOkHttpClient.fromEnv();
var result =
client
.beta()
.agents()
.sessions()
.turns()
.list(
TurnListParams.builder()
.sessionId("sess_123")
.limit(20L)
.order(TurnListParams.Order.of("desc"))
.build());
System.out.println(result.items());
var turn =
client
.beta()
.agents()
.sessions()
.turns()
.retrieve(
TurnRetrieveParams.builder().turnId("turn_123").sessionId("sess_123").build());
System.out.println(turn.subagentId());
# Replace the illustrative IDs and URLs below with your own resource values.
require "openai"
client = OpenAI::Client.new
result = client.beta.agents.sessions.turns.list(
"sess_123",
limit: 20,
order: "desc"
)
puts result.data
turn = client.beta.agents.sessions.turns.retrieve(
"turn_123",
session_id: "sess_123"
)
puts turn.subagent_id
curl "https://api.openai.com/v1/agents/sessions/sess_123/turns?limit=20&order=desc" \
-H "OpenAI-Beta: agents=v1" \
-H "Authorization: Bearer $OPENAI_API_KEY"
curl "https://api.openai.com/v1/agents/sessions/sess_123/turns/turn_123" \
-H "OpenAI-Beta: agents=v1" \
-H "Authorization: Bearer $OPENAI_API_KEY" | jq '.subagent_id'
当 has_more 为 true 时,将返回的 last_id 用作下一页的 after 值。
命令条目包含 turn_id。检索该轮次并读取 subagent_id,以识别执行该命令的委托 Agent。null 子 Agent ID 标识根 Agent 的工作。命令输出截断情况不会被上报。
检查轮次追踪
使用 Platform 控制台检查已完成的轮次及其 Agent 活动。 详细的追踪检索不能通过普通项目 API 密钥获取。控制台追踪端点需要单独的访问权限,不属于受支持的客户 API。
轮次资源包含尽力而为的 usage 以及标识委托工作的 subagent_id。用量在未知时可能为 null,且可能发生变化。请参阅检查子 Agent Token 用量。
若要将 Shell 命令归因,请检索由命令条目的 turn_id 标识的轮次,然后检查 turn.subagent_id。客户 API 不会指示命令输出是否被截断。
模型用量与费用
Agent 在完成任务时可能会进行多次模型调用。每次调用均遵循模型的Token 定价和提示词缓存规则,与 Responses API 一致。请对完成任务所需的所有调用进行成本估算。
哪些内容会产生费用?
每次模型调用可消耗:
- 输入 Token: Agent 指令、工具定义、对话历史、用户输入、文件或图像,以及工具结果。
- 缓存输入 Token: 从匹配的提示词前缀中复用的输入,按模型的缓存输入费率计费。
- 输出 Token: 生成的文本、工具调用参数和推理内容。
推理 Token 按输出 Token 计费。
子 Agent 也可以进行模型调用。在调查模型费用时,请将其记录的轮次用量与根 Agent 的工作一并检查。
在估算时,需考虑根 Agent 和子 Agent 的工作(包括重试),以及适用的工具费用、沙箱计算费用和第三方服务费用。对于有缓存写入定价的模型,将输入写入缓存也会产生费用。下方的 Agents API 用量字段未单独提供缓存写入数量,因此在适用该定价时无法确定确切的模型费用。
提示词缓存
Agent 在会话中持续传递上下文。当连续的模型调用共享相同的提示词前缀时,提示词缓存可以复用之前的处理结果。模型会生成新的响应;缓存不会重放旧的回答。维持会话并不保证缓存命中。复用取决于前缀匹配以及模型的缓存资格和生命周期规则。
在实际可行的情况下,保持初始指令和工具定义的稳定,并将新任务的详细信息放在后续消息中。使用工具搜索时,新发现的定义会被追加到对话末尾,从而为早期内容的缓存复用提供保障。有关特定模型的规则,请参阅提示词缓存。
较高的缓存输入占比并不能衡量总任务成本的节省。缓存输入仍会计费,且重复调用可能处理大量历史记录。请比较以您的应用程序所需质量和延迟完成同一任务的成本。
了解 Token 用量
会话和轮次资源提供尽力而为的 usage。在未知时其值可能为 null,且随着计费数据的到达,已记录的数值可能发生变化。缺少用量数据并不意味着用量为零。这些数据不是最终账单。
已记录的用量对象包含以下 Token 类别:
{
"input_tokens": 5000,
"input_tokens_details": {
"cached_tokens": 1500
},
"output_tokens": 900,
"output_tokens_details": {
"reasoning_tokens": 200
},
"total_tokens": 5900
}
在此示例中,Agent 处理了 5,000 个输入 Token,并生成了 900 个输出 Token。在输入 Token 中,有 1,500 个来自缓存。在输出 Token 中,有 200 个为推理 Token。
缓存 Token 已包含在 input_tokens 中,推理 Token 已包含在 output_tokens 中。
检查子 Agent Token 用量
列出或检索会话轮次,并检查每个轮次的 usage。subagent_id 用于标识子 Agent;对于根 Agent 的轮次,其值为 null。当 has_more 为 true 时,以相同的 order 将 last_id 作为 after 传入,以读取剩余轮次。
用量为尽力而为:在未知时可能为 null,且已记录的值可能发生变化。您也可以在追踪控制台中检查每个 Agent 的已记录用量。