追蹤智慧體的即時活動、檢視已完成的工作,並查看詳細的回合追蹤記錄:
- 你可以在平台儀表板中查看工作階段日誌。
- 你可以透過事件和已儲存的歷史記錄追蹤工作階段。
- 你可以檢視回合,並識別委派執行的指令。
- 你可以檢視根智慧體和子代理程式各回合記錄的 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 中有 200 個是推理 Token。
快取 Token 已計入 input_tokens,推理 Token 已計入 output_tokens。
列出或擷取工作階段回合,並檢視每個回合的 usage。subagent_id 用於識別子代理程式;根智慧體回合的此欄位為 null。當 has_more 為 true 時,請將 last_id 作為 after 傳入,並維持相同的 order,以讀取其餘回合。
用量資料會盡力提供:用量未知時可能為 null,且記錄的數值可能變動。你也可以在追蹤儀表板中檢視每個智慧體記錄的用量。