Agentes como Codex e Investigación profunda demuestran que los modelos de razonamiento pueden tardar varios minutos en resolver problemas complejos. El modo en segundo plano te permite ejecutar tareas de larga duración con modelos como GPT-5.2 y GPT-5.2 Pro de forma confiable, sin preocuparte por tiempos de espera agotados ni otros problemas de conectividad.
El modo en segundo plano inicia estas tareas de forma asíncrona, y los desarrolladores pueden consultar periódicamente los objetos de respuesta para comprobar su estado. Para iniciar la generación de una respuesta en segundo plano, realiza una solicitud a la API con background establecido en true:
Las solicitudes en segundo plano de proyectos con retención cero de datos (ZDR) se ejecutan con
store=false. Los datos de respuesta se almacenan temporalmente en disco durante aproximadamente 10
minutos para permitir la ejecución asíncrona y el sondeo.
En los proyectos que usan monitoreo de abusos
modificado, incluido
el monitoreo de abusos modificado mejorado, las solicitudes en primer plano siguen la política de retención
estándar cuando se omite store o se establece en true. Las respuestas en segundo plano se
conservan después del período de sondeo solo cuando se proporciona explícitamente store=true.
Si se omite store o se establece en false en una solicitud en segundo plano, la respuesta
se elimina después de aproximadamente 10 minutos.
1
2
3
4
5
6
7
8curl https://api.openai.com/v1/responses \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"model": "gpt-6-astra",
"input": "Write a very long novel about otters in space.",
"background": true
}'
1
2
3
4
5
6
7
8
9
10import OpenAI from "openai";
const client = new OpenAI();
const resp = await client.responses.create({
model: "gpt-6-astra",
input: "Write a very long novel about otters in space.",
background: true,
});
console.log(resp.status);
1
2
3
4
5
6
7
8
9
10
11from openai import OpenAI
client = OpenAI()
resp = client.responses.create(
model="gpt-6-astra",
input="Write a very long novel about otters in space.",
background=True,
)
print(resp.status)
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
26package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Background: openai.Bool(true),
Input: responses.ResponseNewParamsInputUnion{
OfString: openai.String("Write a very long novel about otters in space."),
},
})
if err != nil {
panic(err)
}
fmt.Println(response.Status)
}
1
2
3
4
5
6
7
8
9
10
11
12
13import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.responses.ResponseCreateParams;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.input("Write a detailed market analysis.")
.background(true)
.build();
var response = client.responses().create(params);
System.out.println(response.status().orElseThrow());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
BackgroundModeEnabled = true,
};
options.InputItems.Add(
ResponseItem.CreateUserMessageItem("Write a very long novel about otters in space.")
);
ResponseResult response = await client.CreateResponseAsync(options);
Console.WriteLine(response.Status);
1
2
3
4
5
6
7
8
9
10require "openai"
client = OpenAI::Client.new
response = client.responses.create(
model: "gpt-6-astra",
input: "Write a detailed market analysis.",
background: true
)
puts(response.status)
Para comprobar el estado de las solicitudes en segundo plano, usa el punto de acceso GET de Responses. Continúa con el sondeo mientras la solicitud esté en el estado queued o in_progress. Cuando sale de estos estados, ha alcanzado un estado final (terminal).
1
2
3curl https://api.openai.com/v1/responses/resp_123 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import OpenAI from "openai";
const client = new OpenAI();
let resp = await client.responses.create({
model: "gpt-6-astra",
input: "Write a very long novel about otters in space.",
background: true,
});
while (resp.status === "queued" || resp.status === "in_progress") {
console.log("Current status: " + resp.status);
await new Promise((resolve) => setTimeout(resolve, 2000)); // wait 2 seconds
resp = await client.responses.retrieve(resp.id);
}
console.log("Final status: " + resp.status + "\nOutput:\n" + resp.output_text);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17from openai import OpenAI
from time import sleep
client = OpenAI()
resp = client.responses.create(
model="gpt-6-astra",
input="Write a very long novel about otters in space.",
background=True,
)
while resp.status in {"queued", "in_progress"}:
print(f"Current status: {resp.status}")
sleep(2)
resp = client.responses.retrieve(resp.id)
print(f"Final status: {resp.status}\nOutput:\n{resp.output_text}")
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
36package main
import (
"context"
"fmt"
"time"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Background: openai.Bool(true),
Input: responses.ResponseNewParamsInputUnion{
OfString: openai.String("Write a very long novel about otters in space."),
},
})
if err != nil {
panic(err)
}
for response.Status == "queued" || response.Status == "in_progress" {
fmt.Println("Current status:", response.Status)
time.Sleep(2 * time.Second)
response, err = client.Responses.Get(context.Background(), response.ID, responses.ResponseGetParams{})
if err != nil {
panic(err)
}
}
fmt.Printf("Final status: %s\nOutput:\n%s\n", response.Status, response.OutputText())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseStatus;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.input("Write a very long novel about otters in space.")
.background(true)
.build();
var response = client.responses().create(params);
while (response.status().filter(ResponseStatus.QUEUED::equals).isPresent()
|| response.status().filter(ResponseStatus.IN_PROGRESS::equals).isPresent()) {
System.out.println("Current status: " + response.status().orElseThrow());
Thread.sleep(1000);
response = client.responses().retrieve(response.id());
}
System.out.println("Final status: " + response.status().orElseThrow());
response.output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text()));
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
28using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
BackgroundModeEnabled = true,
};
options.InputItems.Add(
ResponseItem.CreateUserMessageItem("Write a very long novel about otters in space.")
);
ResponseResult created = await client.CreateResponseAsync(options);
ResponseResult response = await client.GetResponseAsync(created.Id);
while (response.Status is ResponseStatus.Queued or ResponseStatus.InProgress)
{
await Task.Delay(TimeSpan.FromSeconds(1));
response = await client.GetResponseAsync(response.Id);
}
if (response.Status != ResponseStatus.Completed)
{
throw new InvalidOperationException($"Background response ended with status: {response.Status}");
}
Console.WriteLine($"Status: {response.Status}");
Console.WriteLine(response.GetOutputText());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17require "openai"
client = OpenAI::Client.new
response = client.responses.create(
model: "gpt-6-astra",
input: "Write a very long novel about otters in space.",
background: true
)
while [:queued, :in_progress].include?(response.status)
puts("Current status: #{response.status}")
sleep(2)
response = client.responses.retrieve(response.id)
end
puts("Final status: #{response.status}")
puts(response.output_text)
También puedes cancelar una respuesta en curso de esta manera:
1
2
3curl -X POST https://api.openai.com/v1/responses/resp_123/cancel \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY"
1
2
3
4
5
6import OpenAI from "openai";
const client = new OpenAI();
const resp = await client.responses.cancel("resp_123");
console.log(resp.status);
1
2
3
4
5
6
7
8
9
10import os
from openai import OpenAI
response_id = os.environ["OPENAI_RESPONSE_ID"]
client = OpenAI()
resp = client.responses.cancel(response_id)
print(resp.status)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
)
func main() {
client := openai.NewClient()
canceled, err := client.Responses.Cancel(context.Background(), "resp_123")
if err != nil {
panic(err)
}
fmt.Println(canceled.Status)
}
1
2
3
4
5
6
7
8import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
String responseId = "resp_123";
var response = client.responses().cancel(responseId);
System.out.println(response.status());
1
2
3
4
5
6
7
8
9
10
11using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
// Replace this illustrative ID with the background response to cancel.
string responseId = "resp_123";
ResponseResult response = await client.CancelResponseAsync(responseId);
Console.WriteLine(response.Status);
1
2
3
4
5require "openai"
client = OpenAI::Client.new
response = client.responses.cancel("resp_123")
puts(response.status)
Cancelar dos veces es idempotente: las llamadas posteriores simplemente devuelven el objeto Response final.
Puedes crear una Response en segundo plano y comenzar a transmitir sus eventos de inmediato. Esto puede ser útil si prevés que el cliente interrumpirá el streaming y quieres tener la opción de reanudarlo más adelante. Para ello, crea una Response con background y stream establecidos en true. Conviene que lleves un registro de un “cursor” correspondiente al sequence_number que recibes en cada evento de streaming.
Actualmente, el tiempo que tardas en recibir el primer token de una respuesta en segundo plano es
mayor que el de una respuesta síncrona. Estamos trabajando para reducir
esta diferencia de latencia en las próximas semanas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14curl https://api.openai.com/v1/responses \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"model": "gpt-6-astra",
"input": "Write a very long novel about otters in space.",
"background": true,
"stream": true
}'
// To resume:
curl "https://api.openai.com/v1/responses/resp_123?stream=true&starting_after=42" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import OpenAI from "openai";
const client = new OpenAI();
const stream = await client.responses.create({
model: "gpt-6-astra",
input: "Write a very long novel about otters in space.",
background: true,
stream: true,
});
let cursor = null;
for await (const event of stream) {
console.log(event);
cursor = event.sequence_number;
}
// If the connection drops, you can resume streaming from the last cursor (SDK support coming soon):
// const resumedStream = await client.responses.stream(resp.id, { starting_after: cursor });
// for await (const event of resumedStream) { ... }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21from openai import OpenAI
client = OpenAI()
# Fire off an async response but also start streaming immediately
stream = client.responses.create(
model="gpt-6-astra",
input="Write a very long novel about otters in space.",
background=True,
stream=True,
)
cursor = None
for event in stream:
print(event)
cursor = event.sequence_number
# If your connection drops, the response continues running and you can reconnect:
# SDK support for resuming the stream is coming soon.
# for event in client.responses.stream(resp.id, starting_after=cursor):
# print(event)
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
45package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
stream := client.Responses.NewStreaming(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Background: openai.Bool(true),
Input: responses.ResponseNewParamsInputUnion{
OfString: openai.String("Write a very long novel about otters in space."),
},
})
var cursor int64
var responseID string
for stream.Next() {
event := stream.Current()
fmt.Println(event.Type)
cursor = event.SequenceNumber
if event.Response.ID != "" {
responseID = event.Response.ID
}
}
if err := stream.Err(); err != nil {
panic(err)
}
fmt.Printf("response %s last cursor %d\n", responseID, cursor)
// If the connection drops, resume streaming from the last cursor:
// resumed := client.Responses.GetStreaming(
// context.Background(),
// responseID,
// responses.ResponseGetParams{StartingAfter: openai.Int(cursor)},
// )
// for resumed.Next() {
// fmt.Println(resumed.Current().Type)
// }
}
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
57
58
59
60
61
62
63
64
65
66import 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.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseRetrieveParams;
import com.openai.models.responses.ResponseStreamEvent;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.input("Write a very long novel about otters in space.")
.background(true)
.build();
AtomicLong lastSequenceNumber = new AtomicLong(-1);
AtomicReference<String> responseId = new AtomicReference<>("");
AtomicBoolean streamCompleted = new AtomicBoolean(false);
JsonMapper json = new JsonMapper();
try (StreamResponse<ResponseStreamEvent> stream = client.responses().createStreaming(params)) {
stream.stream()
.forEach(
event -> {
lastSequenceNumber.set(json.valueToTree(event).path("sequence_number").asLong());
event
.created()
.ifPresent(
created -> {
responseId.set(created.response().id());
System.out.println("response.created");
});
event
.outputTextDelta()
.ifPresent(
delta -> {
System.out.println("response.output_text.delta");
});
event
.completed()
.ifPresent(
completed -> {
streamCompleted.set(true);
System.out.println("response.completed");
});
});
}
System.out.println(
"Response " + responseId.get() + "; last sequence number " + lastSequenceNumber.get());
if (!streamCompleted.get()) {
try (StreamResponse<ResponseStreamEvent> resumed =
client
.responses()
.retrieveStreaming(
ResponseRetrieveParams.builder()
.responseId(responseId.get())
.startingAfter(lastSequenceNumber.get())
.build())) {
resumed.stream()
.forEach(
event ->
event.outputTextDelta().ifPresent(delta -> System.out.println(delta.delta())));
}
}
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
BackgroundModeEnabled = true,
StreamingEnabled = true,
};
options.InputItems.Add(
ResponseItem.CreateUserMessageItem("Write a very long novel about otters in space.")
);
string? responseId = null;
int lastSequenceNumber = -1;
bool completed = false;
void HandleUpdate(StreamingResponseUpdate update)
{
lastSequenceNumber = update.SequenceNumber;
switch (update)
{
case StreamingResponseCreatedUpdate created:
responseId = created.Response.Id;
break;
case StreamingResponseOutputTextDeltaUpdate text:
Console.Write(text.Delta);
break;
case StreamingResponseCompletedUpdate:
completed = true;
break;
case StreamingResponseFailedUpdate:
throw new InvalidOperationException("The background response failed.");
case StreamingResponseIncompleteUpdate:
throw new InvalidOperationException("The background response was incomplete.");
case StreamingResponseErrorUpdate error:
throw new InvalidOperationException($"The response stream failed: {error.Message}");
}
}
try
{
await foreach (
StreamingResponseUpdate update in client.CreateResponseStreamingAsync(options)
)
{
HandleUpdate(update);
}
}
catch (Exception error)
when (error is HttpRequestException or IOException && responseId is not null)
{
// The background response continues after its streaming connection is interrupted.
}
if (!completed)
{
if (responseId is null)
{
throw new InvalidOperationException("The response stream ended before providing its ID.");
}
GetResponseOptions resumeOptions = new(responseId)
{
StartingAfter = lastSequenceNumber,
StreamingEnabled = true,
};
await foreach (StreamingResponseUpdate update in client.GetResponseStreamingAsync(resumeOptions))
{
HandleUpdate(update);
}
if (!completed)
{
throw new InvalidOperationException(
"The resumed response stream ended before the background response completed."
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25require "openai"
client = OpenAI::Client.new
stream = client.responses.stream(
model: "gpt-6-astra",
input: "Write a very long novel about otters in space.",
background: true
)
last_sequence_number = -1
response_id = ""
stream.each do |event|
puts(event.type)
last_sequence_number = event.sequence_number || last_sequence_number
if event.is_a?(OpenAI::Models::Responses::ResponseCreatedEvent)
response_id = event.response.id
end
end
puts("Response #{response_id}; last sequence number #{last_sequence_number}")
# If the connection drops, resume from the last sequence number:
# client.responses.stream(response_id: response_id, starting_after: last_sequence_number).each do |event|
# puts(event.type)
# end
- Las solicitudes en segundo plano pueden usar
store=false, pero los datos de respuesta se almacenan temporalmente
para permitir la ejecución asíncrona y el sondeo.
- Para cancelar una respuesta síncrona, cierra la conexión
- Solo puedes iniciar un nuevo streaming de una respuesta en segundo plano si la creaste con
stream=true.