Skip to content

Support background execution, reconnect, and steering in azd ai agent invoke #9676

Description

@m5i-work

Summary

Extend azd ai agent invoke to support long-running Responses turns that continue after the client disconnects, can be reconnected to, and can be steered with revised input.

The workflow uses azd's one saved current background response; users do not select responses by ID in the MVP. azd still prints the service-assigned response ID for diagnostics and future recovery features.

This issue covers only the azure.ai.agents extension's remote Responses invoke experience. Tasks, State Stores, local invocation, Invocations, A2A, and explicit response targeting are out of scope.

1. Background

Microsoft Foundry hosted agents support long-running turns through stored background Responses. A background response can continue after its original client disconnects, while its buffered output can be replayed and followed using the response ID and an event sequence cursor.

Hosted agents can also support steering. Steering submits revised input while a turn is active. The new input is queued, the active handler cooperatively winds down, and the replacement turn starts sequentially.

Relevant public documentation:

For Responses, recoverable execution requires a stored background response. Full process recovery also requires the deployed agent to opt into resilient background execution and implement safe checkpointing. azd should not imply that a client flag alone makes arbitrary agent code crash-resilient.

2. Existing invoke interface

Normal remote Responses invocation:

azd ai agent invoke "Plan a trip to Seattle"

The current command:

  • Sends the request with stream=true.
  • Keeps the connection open and prints text deltas until completion.
  • Automatically reuses the saved hosted-agent session.
  • Automatically creates and reuses a Foundry conversation for multi-turn history.
  • Does not request stored background execution.
  • Does not retain the response ID or stream cursor.
  • Cannot reconnect after the command or connection ends.
  • Cannot steer or cancel a response.

Normal multi-turn chat requires no IDs:

azd ai agent invoke "Plan a trip to Seattle"
azd ai agent invoke "Make it three days"
azd ai agent invoke "Add vegetarian restaurants"

Existing related options include:

--session-id
--new-session
--conversation-id
--new-conversation
--version
--agent-endpoint
--input-file
--output raw

Sessions and conversations remain distinct:

  • A session preserves sandbox and filesystem affinity.
  • A conversation preserves Responses message history.
  • Each user turn creates a separate response with its own lifecycle and stream.

3. Proposed additions

# Start a background turn and remain attached
azd ai agent invoke "run the long task" --background

# Press Ctrl-C at any time to detach without cancelling the background turn.
# azd prints and saves the response ID and last processed event cursor so
# reconnecting later does not replay output that was already shown.
azd ai agent invoke --continue

# Alternatively, start a background turn and detach immediately
azd ai agent invoke "run the long task" --background --no-wait

# Continue receiving output from the latest background response
azd ai agent invoke --continue

# Steer the latest response if active, or start the next background
# turn in the saved conversation if it has completed
azd ai agent invoke "use these revised requirements" --continue

# Cancel the latest background response
azd ai agent invoke --cancel

Start background work and remain attached

azd ai agent invoke "run the long task" --background

Expected behavior:

  • Send store=true, background=true, and stream=true.
  • Print and save the response ID as soon as it is known.
  • Stream output using the existing interactive behavior.
  • Track the latest fully processed sequence_number.
  • Automatically reconnect after transient connection failures.
  • Ctrl-C detaches without cancelling the server-side response.
  • On graceful detach, save the response ID and cursor and print:
Detached from response resp_123. The response is still running.
Last sequence: 42

Next:
  azd ai agent invoke --continue

If Ctrl-C occurs before azd receives a response ID, explain that the response might still be running but azd cannot reconnect to it.

Start background work and detach immediately

azd ai agent invoke "run the long task" --background --no-wait

Expected behavior:

  • Send store=true, background=true, and stream=true.
  • Read through the first lifecycle event that identifies the response, then detach.
  • Print and save its response, session, and conversation IDs; cursor state is managed internally.
  • Print azd ai agent invoke --continue as the next step.
  • Require --background.

Continue receiving output

azd ai agent invoke --continue

Expected behavior:

  • Select the latest saved background response for the current agent context.
  • Use the saved cursor when available.
  • Replay buffered events and continue with live events.
  • If the response is already terminal, print its stored result and exit.
  • Automatically reconnect after transient disconnections.

azd manages the sequence_number cursor automatically and uses the latest saved value for reconnect. It does not print cursor updates while output is streaming or after normal completion. A graceful Ctrl-C detach prints the exact last processed cursor; explicit cursor override is deferred to a future optimization.

If recovery produces another response.in_progress snapshot, azd should print a prominent reset marker, render the authoritative checkpointed output from that snapshot, and then continue with subsequent deltas. The MVP uses the same append-only behavior for TTY and non-TTY output rather than redrawing prior terminal content.

Steer or continue with new input

azd ai agent invoke "use these revised requirements" --continue

Expected behavior:

  1. Resolve the saved current background response.
  2. Retrieve its current status.
  3. If it is active:
    • Create a replacement linked through previous_response_id.
    • Reuse the compatible session.
    • Follow the replacement response.
  4. If it is terminal:
    • Create the next background turn in the saved conversation.
    • Follow the new response.

Steering is cooperative. The superseded response might become cancelled, including with no partial output. That is an expected outcome, not an invoke failure.

Steering always targets the saved current response in the saved current session and conversation. The conversation remains sequential: the replacement queues behind the active response while it winds down, rather than creating concurrent work or a history fork.

Cancel the current response

azd ai agent invoke --cancel

Expected behavior:

  • Cancel the saved current background response.
  • If the response is already terminal, report its status without failing.
  • Keep cancellation distinct from:
    • Ctrl-C, which detaches.
    • azd ai agent sessions stop, which controls session compute.

Single-current-response rules

The MVP retains one current background response for the selected agent context.

  • Before starting an ordinary or background turn, azd checks a saved nonterminal response against the service. If it is still active, reject the new turn and direct the user to invoke <message> --continue to steer or invoke --cancel to stop it.
  • A steering replacement becomes the saved current response.
  • After the saved response is terminal, a successfully accepted ordinary foreground turn clears the old background record because the conversation has advanced outside the background lifecycle.
  • Starting or selecting a different session or conversation is rejected while the saved response is active.
  • Once the saved response is terminal, starting or selecting a different session or conversation clears the background record without cancelling server-side work.
  • Cross-process races, user-identity-aware local state, multiple saved responses, and explicit response targeting are future optimizations.

Flag rules

  • --no-wait requires --background.
  • --continue and --cancel are mutually exclusive.
  • --continue with a message implies stored background execution.
  • --continue without a message receives output from existing work.
  • --cancel does not accept a message.
  • Following or cancelling should reject incompatible --new-session and --new-conversation options.
  • Steering always uses the saved current session and conversation.
  • Message-free operations in multi-agent projects support explicit selection with --agent-name.
  • The MVP stores one current background response under the existing agent context key and retains its session and conversation IDs.
  • --output raw is not supported with the new background response lifecycle options; existing foreground raw output remains unchanged.
  • Background Responses ignore the existing overall --timeout and can remain attached indefinitely.

4. Multi-turn example

# Turn 1: normal foreground response
azd ai agent invoke "Plan a three-day trip to Seattle"

# Turn 2: normal multi-turn continuation; no IDs are needed
azd ai agent invoke "Add vegetarian restaurants"

# Turn 3: start a long-running background response and detach after
# azd captures and saves its identity
azd ai agent invoke \
  "Research current prices for every option" \
  --background \
  --no-wait

# A normal foreground turn is rejected while the background response is active
azd ai agent invoke "Summarize the options"

# ERROR: A background response is still running in the current conversation.
#
# To revise the active turn:
#   azd ai agent invoke "Summarize the options" --continue
#
# To stop it:
#   azd ai agent invoke --cancel

# Starting another background turn is rejected for the same reason
azd ai agent invoke \
  "Produce a detailed itinerary" \
  --background

# ERROR: A background response is still running in the current conversation.

# Follow the current response without creating another turn
azd ai agent invoke --continue

# If it is still active, Ctrl-C detaches without cancelling it.

# Submit revised input to the active response.
# This steers the current turn and follows its replacement.
azd ai agent invoke \
  "Only consider options under $1,000" \
  --continue

# After the replacement completes, message-bearing --continue starts
# the next background turn rather than steering
azd ai agent invoke \
  "Produce the final detailed itinerary" \
  --continue

# After that background turn completes, ordinary multi-turn invocation
# works again and clears the terminal background record
azd ai agent invoke "Summarize the best option"

While the saved background response is active:

Command Result
invoke "message" Rejected
invoke "message" --background Rejected
invoke --continue Follow current output
invoke "message" --continue Steer the current turn
invoke --cancel Cancel the current turn

After the saved response becomes terminal:

Command Result
invoke "message" Start a normal foreground next turn
invoke "message" --background Start a new background next turn
invoke "message" --continue Start a new background next turn
invoke --continue Replay or retrieve the terminal result
invoke --cancel Report the terminal status without failing

5. Future optimizations

The following improvements are outside the initial implementation scope.

Explicit response and cursor selection

The MVP operates only on the locally saved current background response. Future options can target another response or override its reconnect cursor:

azd ai agent invoke --continue --response-id resp_123
azd ai agent invoke --cancel --response-id resp_123

azd ai agent invoke \
  --continue \
  --response-id resp_123 \
  --starting-after 42

This requires defining behavior when the response's session, conversation, version, cursor, or other local metadata is unavailable.

Multiple saved background responses

The MVP retains one current background response per agent context. A future implementation can retain per-response history so users can discover and reconnect to older Responses.

This concerns local discovery and Responses from different sessions or conversations. Turns within one conversation remain sequential and do not execute concurrently.

User-identity-aware local state

The MVP reuses the existing local agent context key. A future implementation can scope saved sessions, conversations, and background Responses by --user-identity, preventing different service-side isolation partitions from overwriting each other's local selection.

Metadata

Metadata

Labels

aiAIarea/uxUX, prompts, output formattingenhancementNew feature or improvementext-agentsazure.ai.agents extension

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions