跟踪智能体的实时活动,查看已完成的工作,并审查详细的轮次追踪记录:
- 您可以在平台控制台中查看会话日志。
- 您可以通过会话事件和保存的历史记录跟踪会话。
- 您可以查看轮次,识别委派执行的命令。
- 您可以查看根智能体和子智能体各轮次记录的 Token 用量。
前往 platform.openai.com/logs?api=agents,然后打开 智能体 选项卡。
按 ID 搜索会话,查看其轮次、工具调用和子智能体。
请参阅追踪指南,在仪表板中查看已记录的模型响应、工具调用和子智能体活动,或通过公共 API 将会话追踪记录导出为 OTLP JSON 格式。
跟踪事件并查看会话历史记录
每个会话都提供一个事件流,实时显示智能体正在执行的操作。请设置 OPENAI_API_KEY,并将这些示例中的演示会话 ID 替换为您保存的会话 ID:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// 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();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# 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))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26// 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)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// 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));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 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
1
2
3
4
5curl -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
要查看已经执行的工作,请检索会话中保存的条目:
1
2
3
4
5
6
7
8
9
10// 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);
1
2
3
4
5
6
7
8# 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())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 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());
1
2
3
4
5
6
7
8
9
10# 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
1
2
3
4curl \
-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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 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);
1
2
3
4
5
6
7
8
9
10
11# 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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27// 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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29// 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());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 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
1
2
3
4
5
6
7curl "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,即可识别受委派执行该命令的智能体。子智能体 ID 为 null 表示工作由根智能体执行。系统不会报告命令输出是否被截断。
使用平台仪表板查看已完成的轮次及其智能体活动。
要通过公共 API 获取已记录的追踪数据,请使用项目 API 密钥调用会话追踪导出端点。仪表板的追踪端点仍与受支持的客户 API 相互独立。
轮次资源包含尽力提供的 usage,以及用于标识委派工作的 subagent_id。用量未知时可为 null,且可能发生变化。请参阅查看子智能体 Token 用量。
要确定 Shell 命令由哪个智能体执行,请根据命令条目中的
turn_id 检索对应轮次,然后查看 turn.subagent_id。客户 API 不会指明
命令输出是否被截断。
智能体在完成任务时可能会多次调用模型。与 Responses API 一样,每次调用都遵循该模型的 Token 定价和提示缓存规则。估算费用时,请计入完成任务所需的所有调用。
每次模型调用都可能消耗以下 Token:
- 输入 Token: 智能体指令、工具定义、对话历史记录、用户输入、文件或图像,以及工具结果。
- 缓存输入 Token: 从匹配的提示前缀中复用的输入,按模型的缓存输入费率计费。
- 输出 Token: 生成的文本、工具调用参数和推理。
推理 Token 按输出 Token 计费。
子智能体也可以调用模型。分析模型费用时,请同时查看子智能体记录的轮次用量和根智能体执行的工作。
请计入根智能体和子智能体执行的工作,包括重试,以及所有适用的工具、沙盒计算和第三方服务费用。对于缓存写入单独计价的模型,将输入写入缓存也会产生费用。下方的 Agents API 用量字段不提供单独的缓存写入计数,因此,在适用此类定价时,无法仅凭这些字段确定准确的模型费用。
智能体会在会话内沿用上下文。当连续的模型调用共享相同的提示前缀时,提示缓存可以复用此前对该前缀的处理结果。模型会生成新的响应,缓存不会重放旧答案。保持会话并不保证命中缓存。能否复用取决于前缀是否匹配,以及模型对缓存适用条件和有效期的规定。
在可行的情况下,保持初始指令和工具定义稳定,并将新的任务详情放在后续消息中。使用工具搜索时,发现的工具定义会添加到对话末尾,从而保留此前的内容以供缓存复用。有关各模型的具体规则,请参阅提示缓存。
缓存输入占比高,并不能衡量任务总费用节省了多少。缓存输入仍需计费,而反复调用可能会处理大量历史记录。请在满足应用所需质量和延迟的前提下,比较完成同一任务的费用。
会话和轮次资源会尽力提供 usage。用量未知时,该值可为 null,而记录的计数可能会随着核算数据的到达而变化。缺少用量数据并不意味着用量为零。这些计数并非最终账单。
记录的用量对象包含以下 Token 类别:
1234567891011{
"input_tokens": 5000,
"input_tokens_details": {
"cached_tokens": 1500
},
"output_tokens": 900,
"output_tokens_details": {
"reasoning_tokens": 200
},
"total_tokens": 5900
}
在此示例中,智能体处理了 5,000 个输入 Token,并生成了 900 个输出 Token。其中,输入 Token 中有 1,500 个为缓存 Token,输出 Token 中有 200 个为推理 Token。
缓存 Token 包含在 input_tokens 中,推理 Token 包含在 output_tokens 中。
列出或检索会话轮次,并查看每个轮次的 usage。subagent_id 用于标识子智能体;对于根智能体轮次,该值为 null。当 has_more 为 true 时,将 last_id 作为 after 传入,并保持 order 不变,以读取剩余轮次。
系统会尽力提供用量数据:用量未知时可为 null,且记录的值可能发生变化。您也可以在追踪控制台中查看每个智能体记录的用量。