Skip to content

Spike: measure ACA dynamic-sessions transport cap to pick the runner API branch (S vs P) #312

Description

@jrob5756

Parent: #284 — Agent-in-Sandbox via a remote aca provider.
Design doc: docs/aca-provider.design.md — Open Question #1 (Blocking / Phase 0), DD3.

Why (blocking)

The aca provider relocates an agent's whole runtime into an ACA custom-container
dynamic session. A single agent turn can run for minutes, so the runner transport
must survive ACA's request/idle-timeout limits. Two ACA limits must not be conflated:

  • Per-request forwarded-duration cap — how long one request may stay open.
    Undocumented for sessions; general ACA ingress idle-timeout defaults to 4 min,
    premium max 30 min. This is the real cut-off risk.
  • Inter-request Timed cooldown (300–3600 s) — how long an idle session
    survives between requests, reset each time the session API is called.

Two candidate transport branches with identical event/result semantics:

  • Branch S (preferred) — single streaming request. One POST /execute streams
    NDJSON event frames until a terminal result frame. True incremental events +
    mid-call partials + real interrupt. Viable only if one request can stay open for
    the whole turn.
  • Branch P (fallback) — submit + poll. POST /execute returns a job id; the
    host polls for event batches. Each poll is a fresh request under the cap and
    resets the cooldown. Survives a short cap at the cost of coarser streaming/interrupt.

This spike gates the build and fixes the conditional streaming_events /
interrupt capabilities. No provider code should land before it resolves.

Method

  • Stand up a throwaway custom-container session pool (DD6 two-step deploy: push
    image to ACR, then az containerapp sessionpool create --container-type CustomContainer …).
  • Bake a trivial heartbeat runner into the image: emits one NDJSON frame/second,
    then a terminal result frame.
  • Drive it from a standalone probe script (no Conductor dependency).

What to measure

  1. True per-request forwarded-duration cap — hold a single chunked response
    open and record when the sessions endpoint cuts it off. Repeat with premium
    ingress and its request idle-timeout raised toward the 30-min max.
  2. Stream durability — does steady chunked streaming survive ≥10 min without
    a drop?
  3. Resumability — can a dropped stream be resumed by replaying from a
    Last-Event-ID cursor (AG-UI style)?

Decision rule

  • One request reliably survives a full multi-minute turn → Branch S
    (streaming_events=True, real interrupt).
  • Request is capped short → Branch P (streaming_events=False,
    hard-abort-only interrupt via stopSession).

Deliverables / acceptance criteria

  • The probe script + a short throwaway Dockerfile / pool setup (or scripted az commands).
  • Measured per-request cap (default ingress and premium with idle-timeout raised).
  • Pass/fail on ≥10-min stream durability.
  • Finding on Last-Event-ID resume feasibility.
  • A written recommendation — Branch S or Branch P — with the resulting
    streaming_events / interrupt capability values, folded back into
    docs/aca-provider.design.md (DD3 + capabilities table).

References

Metadata

Metadata

Assignees

Labels

area:providerSDK providers (Copilot, Claude)enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions