Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Instradamento consente di reindirizzare un agente ospitato a esecuzione prolungata mentre è ancora in esecuzione. Un nuovo input si mette in coda dietro al turno attivo e il gestore in esecuzione si conclude in modo cooperativo. Questo approccio evita di rifiutare il nuovo turno o correre due turni contemporaneamente.
Note
Gli agenti a esecuzione prolungata sono in anteprima. Le API e le versioni dei pacchetti sono soggette a modifiche.
Attivare l'instradamento
Protocollo di risposte
Imposta steerable_conversations=True su ResponsesServerOptions:
app = ResponsesAgentServerHost(
options=ResponsesServerOptions(steerable_conversations=True),
)
Un secondo turno che arriva su code di conversazioni occupate e il gestore corrente annulla in modo cooperativo. Questo approccio evita la restituzione di 409 conversation_locked. Inviare il messaggio di follow-up come una nuova risposta con previous_response_id impostato sulla risposta in corso e lo stesso agent_session_id.
Invocazioni e primitive di task
Passare steerable=True a @multi_turn_task:
@multi_turn_task(name="conv", steerable=True)
async def conv(ctx: TaskContext[dict]) -> dict:
return await llm(ctx.input)
# A .start() against an in-flight chain queues instead of raising.
r1 = asyncio.create_task(conv.start(task_id="c1", input={"msg": "Plan a trip to Rome"}))
await asyncio.sleep(0.05)
r2 = asyncio.create_task(conv.start(task_id="c1", input={"msg": "Actually, Paris"}))
# r1 resolves with turn 1's outcome; r2 resolves with turn 2's outcome.
Senza steerable=True, un oggetto simultaneo .start() in una catena in volo genera TaskConflictError.
Concludere il turno attivo
Quando un elemento viene accodato, il framework segnala il gestore in esecuzione tramite il segnale di annullamento cooperativo. Un handler instradabile dovrebbe verificarlo in corrispondenza di punti sicuri e terminare anticipatamente, in modo che il turno in coda possa subentrare:
@multi_turn_task(name="conv", steerable=True)
async def conv(ctx: TaskContext[dict]) -> dict:
for step in plan:
if ctx.cancel.is_set() and ctx.pending_input_count > 0:
# A newer turn is waiting - stop at this boundary and let it run.
return partial_result
await do_step(step)
return final_result
Osservabilità della guida nel contesto:
| Campo | Meaning |
|---|---|
ctx.is_steered_turn |
True se questo turno è stato promosso dalla coda. |
ctx.pending_input_count |
Numero di turni più recenti attualmente in coda. |
ctx.cancel |
Segnale di annullamento cooperativo; impostato quando un turno in coda è in attesa. |
Ordinare i turni con una precondizione
Quando un client deve tenere conto dell'ordine dei messaggi, passare if_last_input_id in modo che un chiamante non aggiornato non possa aggiungere messaggi dopo che un altro chiamante ha fatto avanzare la catena. È l'equivalente, per la coda di input, di un HTTP If-Match:
await conv.start(task_id="c1", input=new_msg, if_last_input_id=prev_input_id)
Se l'ultimo input accettato della catena non corrisponde più, la chiamata genera LastInputIdPreconditionFailed.
Gestire una coda completa
La coda di instradamento è delimitata. Quando è piena, un'operazione di accodamento solleva SteeringQueueFull; mostrare all'utente un chiaro messaggio di "attendere" invece di scartare l'input silenziosamente:
try:
run = await conv.start(task_id="c1", input=new_msg)
except SteeringQueueFull:
return {"status": "busy", "detail": "Too many pending turns; try again shortly."}
Le conversazioni instradabili sono sequenziali, non ramificate: l'input più recente può mettersi in coda dietro al turno attivo o interromperlo, ma la conversazione mantiene comunque un unico turno più recente e una cronologia ordinata.