Sigue la actividad del agente en tiempo real, inspecciona el trabajo completado y revisa las trazas detalladas de los turnos:
- Puedes ver los registros de la sesión en el panel de la plataforma.
- Puedes seguir la sesión a través de sus eventos y del historial guardado.
- Puedes inspeccionar los turnos e identificar los comandos cuya ejecución se delegó.
- Puedes consultar el uso de tokens registrado en los turnos del agente raíz y de los subagentes.
Ve a platform.openai.com/logs?api=agents y abre la pestaña Agentes.
Busca una sesión por su ID para inspeccionar sus turnos, llamadas a herramientas y subagentes.
Consulta la guía de trazas para inspeccionar en el panel los registros de las respuestas del modelo, las llamadas a herramientas y la actividad de los subagentes, o exporta las trazas de la sesión en formato JSON de OTLP mediante la API pública.
Cada sesión ofrece un flujo de eventos que muestra en tiempo real lo que hace el agente. Configura OPENAI_API_KEY y reemplaza el ID de sesión que aparece en estos ejemplos por el que guardaste:
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.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.ObjectMappers;
import com.openai.core.http.StreamResponse;
import com.openai.models.beta.agents.AgentSessionEvent;
OpenAIClient client = OpenAIOkHttpClient.fromEnv();
var json = ObjectMappers.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"
El flujo sigue abierto incluso cuando se producen eventos de inactividad, para que puedas seguir también el trabajo en cola. Presiona Ctrl+C para dejar de observar el flujo.
Mientras se ejecuta la sesión, verás eventos como estos:
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
Para inspeccionar el trabajo que ya se realizó, recupera los elementos guardados de la sesión:
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"
Puedes acceder a los turnos de la sesión mediante la API pública. Usa el turn_id de un elemento de comando junto con el ID de sesión que guardaste. El ejemplo en Go usa la paginación nativa del SDK para buscar entre los turnos del agente raíz y de los subagentes. Luego recupera el turno correspondiente del agente al que pertenece. Reemplaza los ID de ejemplo por los de tu sesión. El ejemplo de cURL requiere jq:
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
30
31
32
33
34
35// Replace the illustrative session and turn IDs with values from your command item.
import OpenAI from "openai";
const client = new OpenAI();
async function findTurn(sessionId, turnId) {
for await (const turn of client.beta.agents.sessions.turns.list(sessionId, {
limit: 100,
})) {
if (turn.id === turnId) {
return client.beta.agents.sessions.turns.retrieve(turnId, {
session_id: sessionId,
});
}
}
for await (const subagent of client.beta.agents.sessions.subagents.list(
sessionId,
{ limit: 100 }
)) {
for await (const turn of client.beta.agents.sessions.subagents.turns.list(
subagent.id,
{ session_id: sessionId, limit: 100 }
)) {
if (turn.id === turnId) {
return client.beta.agents.sessions.subagents.turns.retrieve(turnId, {
session_id: sessionId,
subagent_id: subagent.id,
});
}
}
}
throw new Error(`Turn ${turnId} not found in session ${sessionId}`);
}
const turn = await findTurn("sess_123", "turn_123");
console.log(turn.subagent_id || "main agent");
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.
from openai import OpenAI
def find_turn(client, session_id, turn_id):
# Native SDK pagination searches every page for the owning agent.
for turn in client.beta.agents.sessions.turns.list(session_id, limit=100):
if turn.id == turn_id:
return client.beta.agents.sessions.turns.retrieve(
turn_id, session_id=session_id
)
for subagent in client.beta.agents.sessions.subagents.list(session_id, limit=100):
turns = client.beta.agents.sessions.subagents.turns.list(
subagent.id, session_id=session_id, limit=100
)
for turn in turns:
if turn.id == turn_id:
return client.beta.agents.sessions.subagents.turns.retrieve(
turn_id, session_id=session_id, subagent_id=subagent.id
)
raise ValueError(f"Turn {turn_id} not found in session {session_id}")
turn = find_turn(OpenAI(), "sess_123", "turn_123")
print(turn.subagent_id or "main agent")
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52// Replace the illustrative session and turn IDs with values from your command item.
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
)
ctx := context.Background()
client := openai.NewClient()
turn, err := findTurn(ctx, &client, "sess_123", "turn_123")
if err != nil {
panic(err)
}
if turn.SubagentID == "" {
fmt.Println("main agent")
} else {
fmt.Println(turn.SubagentID)
}
// findTurn discovers the owning agent using native SDK pagination.
func findTurn(ctx context.Context, client *openai.Client, sessionID, turnID string) (*openai.Turn, error) {
turns := client.Beta.Agents.Sessions.Turns.ListAutoPaging(ctx, sessionID,
openai.BetaAgentSessionTurnListParams{Limit: openai.Int(100)})
for turns.Next() {
if turns.Current().ID == turnID {
return client.Beta.Agents.Sessions.Turns.Get(ctx, sessionID, turnID)
}
}
if err := turns.Err(); err != nil {
return nil, err
}
subagents := client.Beta.Agents.Sessions.Subagents.ListAutoPaging(ctx, sessionID,
openai.BetaAgentSessionSubagentListParams{Limit: openai.Int(100)})
for subagents.Next() {
subagent := subagents.Current()
childTurns := client.Beta.Agents.Sessions.Subagents.Turns.ListAutoPaging(ctx, sessionID, subagent.ID,
openai.BetaAgentSessionSubagentTurnListParams{Limit: openai.Int(100)})
for childTurns.Next() {
if childTurns.Current().ID == turnID {
return client.Beta.Agents.Sessions.Subagents.Turns.Get(ctx, sessionID, subagent.ID, turnID)
}
}
if err := childTurns.Err(); err != nil {
return nil, err
}
}
if err := subagents.Err(); err != nil {
return nil, err
}
return nil, fmt.Errorf("turn %s not found in session %s", turnID, sessionID)
}
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56// Replace the illustrative session and turn IDs with values from your command item.
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.beta.agents.sessions.subagents.SubagentListParams;
import com.openai.models.beta.agents.sessions.turns.Turn;
import com.openai.models.beta.agents.sessions.turns.TurnListParams;
import com.openai.models.beta.agents.sessions.turns.TurnRetrieveParams;
OpenAIClient client = OpenAIOkHttpClient.fromEnv();
var turn = findTurn(client, "sess_123", "turn_123");
System.out.println(turn.subagentId().orElse("main agent"));
// Discover the owning agent using native SDK pagination before retrieving the turn.
static Turn findTurn(OpenAIClient client, String sessionId, String turnId) {
var sessions = client.beta().agents().sessions();
var turns =
sessions.turns().list(TurnListParams.builder().sessionId(sessionId).limit(100L).build());
for (var turn : turns.autoPager()) {
if (turn.id().equals(turnId)) {
return sessions
.turns()
.retrieve(TurnRetrieveParams.builder().sessionId(sessionId).turnId(turnId).build());
}
}
var subagents =
sessions
.subagents()
.list(SubagentListParams.builder().sessionId(sessionId).limit(100L).build());
for (var subagent : subagents.autoPager()) {
var childTurns =
sessions
.subagents()
.turns()
.list(
com.openai.models.beta.agents.sessions.subagents.turns.TurnListParams.builder()
.sessionId(sessionId)
.subagentId(subagent.id())
.limit(100L)
.build());
for (var turn : childTurns.autoPager()) {
if (turn.id().equals(turnId)) {
return sessions
.subagents()
.turns()
.retrieve(
com.openai.models.beta.agents.sessions.subagents.turns.TurnRetrieveParams
.builder()
.sessionId(sessionId)
.subagentId(subagent.id())
.turnId(turnId)
.build());
}
}
}
throw new IllegalArgumentException("Turn " + turnId + " not found in session " + sessionId);
}
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
30# Replace the illustrative IDs below with values from your command item.
require "openai"
# Discover the owning agent before retrieving the turn.
def find_turn(client, session_id, turn_id)
turns = client.beta.agents.sessions.turns.list(session_id, limit: 100)
turns.auto_paging_each do |turn|
if turn.id == turn_id
return client.beta.agents.sessions.turns.retrieve(turn_id, session_id: session_id)
end
end
subagents = client.beta.agents.sessions.subagents.list(session_id, limit: 100)
subagents.auto_paging_each do |subagent|
turns = client.beta.agents.sessions.subagents.turns.list(
subagent.id, session_id: session_id, limit: 100
)
turns.auto_paging_each do |turn|
if turn.id == turn_id
return client.beta.agents.sessions.subagents.turns.retrieve(
turn_id, session_id: session_id, subagent_id: subagent.id
)
end
end
end
raise "Turn #{turn_id} not found in session #{session_id}"
end
turn = find_turn(OpenAI::Client.new, "sess_123", "turn_123")
puts(turn.subagent_id || "main agent")
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'
Si usas la paginación manual, pasa el last_id que recibiste como valor de after para la página siguiente cuando has_more sea true. El ejemplo en Go recorre estas páginas automáticamente.
Los elementos de comando contienen turn_id. Recupera ese turno y consulta subagent_id para identificar al subagente que ejecutó el comando. Si el ID del subagente es null, el agente raíz realizó el trabajo. No se informa si se truncó la salida del comando.
Usa el panel de la plataforma para inspeccionar un turno completado y la actividad del agente durante ese turno.
Para recuperar las trazas registradas mediante la API pública, usa el punto de acceso para exportar trazas de sesiones con una clave de API del proyecto. Los puntos de acceso a las trazas del panel siguen siendo independientes de la API con soporte para clientes.
Los recursos de turno incluyen los datos de usage que se hayan podido registrar y un subagent_id que identifica el trabajo delegado. Si se desconoce el uso, su valor puede ser null. Los datos de uso pueden cambiar. Consulta Inspeccionar el uso de tokens de los subagentes.
Para saber qué agente ejecutó un comando de shell, recupera el turno identificado por el campo
turn_id del elemento de comando y consulta turn.subagent_id. La API para clientes no indica
si se truncó la salida del comando.
Consulta Errores y recuperación para inspeccionar los errores,
elegir cómo recuperarte y volver a intentarlo de forma segura.
Un agente puede hacer varias llamadas al modelo para completar una tarea. A cada llamada se le aplican los precios por token y las reglas de almacenamiento en caché de prompts del modelo, al igual que en la API de Responses. Para estimar el costo, ten en cuenta todas las llamadas necesarias para completar la tarea.
Cada llamada al modelo puede consumir:
- Tokens de entrada: instrucciones del agente, definiciones de herramientas, historial de la conversación, entrada del usuario, archivos o imágenes y resultados de las herramientas.
- Tokens de entrada en caché: entrada que se reutiliza cuando coincide el prefijo del prompt y que se factura según la tarifa del modelo para la entrada en caché.
- Tokens de salida: texto generado, argumentos de las llamadas a herramientas y razonamiento.
Los tokens de razonamiento se facturan como tokens de salida.
Los subagentes también pueden hacer llamadas al modelo. Al investigar los costos del modelo, revisa el uso registrado en sus turnos junto con el trabajo del agente raíz.
Ten en cuenta el trabajo del agente raíz y de los subagentes, incluidos los reintentos, además de los cargos que correspondan por herramientas, recursos de cómputo del sandbox y servicios de terceros. En los modelos que cobran por escribir en la caché, guardar la entrada en la caché también tiene un costo. Los campos de uso de la API de Agentes que se muestran a continuación no incluyen un recuento separado de tokens escritos en la caché, por lo que no permiten determinar el cargo exacto por uso del modelo cuando se aplica esa tarifa.
Los agentes conservan el contexto a lo largo de una sesión. Cuando varias llamadas sucesivas al modelo comparten el mismo prefijo del prompt, el almacenamiento en caché de prompts permite reutilizar el procesamiento previo de ese prefijo. El modelo genera una respuesta nueva. La caché no reproduce una respuesta anterior. Mantener una sesión abierta no garantiza un acierto de caché. La reutilización depende de que el prefijo coincida y de las reglas del modelo sobre qué se puede almacenar en la caché y durante cuánto tiempo.
En la medida de lo posible, mantén estables las instrucciones iniciales y las definiciones de herramientas, e incluye los nuevos detalles de la tarea en mensajes posteriores. Con la búsqueda de herramientas, las definiciones encontradas se agregan al final de la conversación, de modo que el contenido anterior se conserva y puede reutilizarse desde la caché. Consulta Almacenamiento en caché de prompts para conocer las reglas de cada modelo.
Un porcentaje alto de tokens de entrada en caché no indica cuánto ahorras en el costo total de la tarea. La entrada en caché también se factura, y las llamadas sucesivas pueden procesar un historial extenso. Compara el costo de completar la misma tarea con la calidad y la latencia que necesita tu aplicación.
Los recursos de sesión y de turno exponen en usage los datos de uso que se hayan podido registrar. El valor puede ser null si se desconoce el uso, y los recuentos registrados pueden cambiar a medida que llegan los datos de consumo. La ausencia de datos de uso no significa que el consumo sea cero. Estos recuentos no constituyen una factura definitiva.
Un objeto de uso registrado contiene las siguientes categorías de tokens:
1234567891011{
"input_tokens": 5000,
"input_tokens_details": {
"cached_tokens": 1500
},
"output_tokens": 900,
"output_tokens_details": {
"reasoning_tokens": 200
},
"total_tokens": 5900
}
En este ejemplo, el agente procesó 5000 tokens de entrada y generó 900 tokens de salida. De los tokens de entrada, 1500 estaban en caché. De los tokens de salida, 200 eran tokens de razonamiento.
Los tokens en caché se incluyen en input_tokens y los tokens de razonamiento se incluyen en output_tokens.
Enumera o recupera los turnos de la sesión y consulta el campo usage de cada turno. El campo subagent_id identifica al subagente y su valor es null en los turnos del agente raíz. Cuando has_more sea true, pasa last_id como valor de after y conserva el valor de order para leer los turnos restantes.
Los datos de uso reflejan lo que se haya podido registrar. Si se desconoce el uso, su valor puede ser null, y los valores registrados pueden cambiar. También puedes consultar el uso registrado de cada agente en el panel de trazas.