Skip to content

docs: refine Durable agent loop architecture and delivery plan - #234

Merged
Laveesh Rohra (larohra) merged 13 commits into
feature/durable-agent-loopfrom
larohra/durable-loop-review
Sep 25, 2026
Merged

Laveesh Rohra (larohra) merged 13 commits into
feature/durable-agent-loopfrom
larohra/durable-loop-review

Conversation

@larohra

@larohra Laveesh Rohra (larohra) commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Refine FRD 0009 (#226) into a usable Durable v1 design and delivery plan, incorporating architecture review and human decisions.

  • Honor existing whole-run timeout with replay-safe deadlines, Entity-side recovery and truthful late-effect handling.
  • Co-locate each agent's HTTP submission and management in one function so its individual function key works for both; retain distinct per-agent auth policies.
  • Preserve session identity/history/receipts across deployments without deployment-version pinning. Operators own breaking changes and migrations.
  • Defer inbound MCP to post-v1, retain outbound MCP tools, and track seven follow-ups with explicit deferred/optional/candidate status.
  • Consolidate the core into a usable C2 PR with parallel work packages, followed by Sandbox C3 and qualification C4.

Does this introduce a breaking change?

[ ] Yes
[x] No

Documentation-only design revision; no runtime behavior changes here.

Pull Request Type

What kind of change does this Pull Request introduce?

[ ] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[x] Documentation content changes
[ ] Other... Please describe:

How to Test

  • Get the code
git clone https://github.com/Azure/azure-functions-agents-runtime.git
cd azure-functions-agents-runtime
git checkout larohra/durable-loop-review
pip install -e .
  • Test the code
git diff --check origin/feature/durable-agent-loop...HEAD

Documentation-only; no runtime tests or cloud qualification performed in this PR. Single-step harness/skills verification is a separate, nonblocking investigation; breaking findings will be addressed in a follow-up PR rather than silently dropping capabilities.

What to Check

Verify that the following are valid

  • Submit/manage paths share the same host-authorized function-key scope. Credential carrier visibility and routing are implementation qualification requirements, not proven by this document.
  • Whole-run timeout, human wait, Entity watchdog, generation fencing and quarantine are mutually consistent.
  • Session continuity does not imply successful execution of incompatible user deployments; no catalog-version gate is introduced.
  • No inbound Durable MCP registrations or qualification gates remain in v1. Ordinary MCP and outbound MCP remain distinct.
  • Core implementation ships real execution and complete lifecycle together; no dead public flags or fake shipped model path.

Other Information

Targets feature/durable-agent-loop, not main; C0 test-only characterization is stacked in #235. Status remains In review pending final architecture sign-off. This PR does not authorize cloud execution or claim production qualification.

Record review findings and preserve whole-run timeout, key-scoped ownership, and inbound MCP design intent.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The FRD has unresolved scope, function-key authorization, MCP registration, and delivery-sequencing inconsistencies.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 3 Medium severity

Open (3)
What changed in this PR

Refines FRD 0009’s Durable agent-loop architecture and staged delivery plan.

Changes:

  • Defines policy, timeout, ownership, retry, and Entity-history behavior.
  • Adds Durable-aware MCP design and registration accounting.
  • Splits implementation into gated delivery slices.
File Description
docs/​frds/​0009-durable-agent-loop.md Expands the architecture, decisions, qualification gates, and delivery plan.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/frds/0009-durable-agent-loop.md Outdated
Comment thread docs/frds/0009-durable-agent-loop.md
Comment thread docs/frds/0009-durable-agent-loop.md Outdated
Comment thread docs/frds/0009-durable-agent-loop.md
Comment thread docs/frds/0009-durable-agent-loop.md Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM. leave non-blocking suggestions and questions.

Defer inbound MCP and track fast-follows, co-locate keyed HTTP operations, preserve sessions across user-managed deployments, and consolidate usable core delivery. Include timeout and recovery clarification from architecture review.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The optional UI behavior and authored HTTP route transformation remain insufficiently defined for implementation.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 2 Low severity

Open (2)
Resolved since last review (3)

Comment thread docs/frds/0009-durable-agent-loop.md Outdated
Comment thread docs/frds/0009-durable-agent-loop.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Authentication, UI bootstrap, quarantine, identity, and module-boundary contracts remain insufficiently resolved.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 3 High severity · 2 Medium severity

Open (5)
Resolved since last review (2)

Comment thread docs/frds/0009-durable-agent-loop.md
Comment thread docs/frds/0009-durable-agent-loop.md Outdated
Comment thread docs/frds/0009-durable-agent-loop.md Outdated
Comment thread docs/frds/0009-durable-agent-loop.md Outdated
Comment thread docs/frds/0009-durable-agent-loop.md Outdated
@larohra
Laveesh Rohra (larohra) added this pull request to stack #236 September 23, 2026 21:21
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The per-entry HTTP registration contract assigns colliding function names when an agent exposes built-in and authored entries.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity · 1 Low severity

Open (2)
Resolved since last review (5)

Comment thread docs/frds/0009-durable-agent-loop.md Outdated
Comment thread docs/frds/0009-durable-agent-loop.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@larohra
Laveesh Rohra (larohra) marked this pull request as ready for review September 23, 2026 22:07
@larohra
Laveesh Rohra (larohra) requested a review from a team as a code owner September 23, 2026 22:07
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

@hallvictoria hallvictoria left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Architecture review follow-up: six design questions that appear unresolved before implementation.

Comment thread docs/frds/0009-durable-agent-loop.md
Comment thread docs/frds/0009-durable-agent-loop.md
Comment thread docs/frds/0009-durable-agent-loop.md
Comment thread docs/frds/0009-durable-agent-loop.md
Comment thread docs/frds/0009-durable-agent-loop.md
Comment thread docs/frds/0009-durable-agent-loop.md
@TsuyoshiUshio

Copy link
Copy Markdown
Contributor

FYI only — not a change request and not a blocker. I am OK to approve this PR.

I wrote this summary of the Durable agent API (FRD 0009 §4.2–§4.13, head 886734d) to help me understand the design. I share it here because it can help other reviewers. Laveesh Rohra (@larohra), if something is wrong, please tell me. You do not need to change the FRD because of this comment.

Note: the FRD defines paths, headers and status codes. It does not yet define the exact request body and response JSON field names. The existing chat API uses {"prompt": "..."}.

1. How to enable (front matter)

---
name: Researcher
builtin_endpoints:
  chat_api: true        # management paths are in the same function
durable:
  enabled: true         # shorthand: durable: true
  limits:               # optional; no defaults
    max_model_steps: 24
    max_tool_calls: 48
  history:
    session_ttl: P10D   # required; ISO-8601 fixed units only
  sandbox_group:        # optional; added in C3
    resource_id: $SANDBOX_GROUP_RESOURCE_ID
    region: $SANDBOX_GROUP_REGION
    disk: python-3.13   # mutually exclusive with disk_id
---
  • durable is inherited from agents.config.yaml to each agent. null clears an inherited value.
  • The existing timeout is the deadline for the complete turn (model steps, tools, retries and human-input waits).
  • Auth: entra, function or admin. anonymous is rejected.
  • Rejected together with Durable: workflows.enabled, subagents, workflows.subagents, builtin_endpoints.mcp (also the builtin_endpoints: true shorthand).

2. Endpoints (under /agents/{slug})

Method and path Purpose
POST /chat (or the authored HTTP route R) Accept a turn. Returns 202, not a synchronous answer
GET /manage/runs/{run_id} Status, result or pending question (polling)
POST /manage/runs/{run_id}/cancel Idempotent, best-effort cancellation
POST /manage/runs/{run_id}/input/{question_id} Idempotent answer to the stored question
GET /manage/sessions Owner-scoped, paginated session list
GET /manage/sessions/{session_id}/history Conversation from the Entity (authoritative)
DELETE /manage/sessions/{session_id} Start deletion; a repeated call returns the same progress
GET /manage/runs/{run_id}/events Optional SSE; not required for v1

For an authored route R, management is below R/manage/... (for example, orders/acme/ask/manage/runs/<id>).

3. Request parameters

Item Location Rule
Idempotency-Key Header (required) [A-Za-z0-9._-]{1,128}, case-sensitive. Missing → 400. Use the same value on retry
x-ms-session-id Header (optional) Continues a session. If absent, the session ID is derived from the key
session_id Body root (optional) Must agree with the header, else 400
Credential x-functions-key / code / Entra Conflicting carriers → 400 ambiguous_credential

4. Responses

Case Response
Accepted 202 with session_id, run_id, request_id, relative status links and the x-ms-session-id header
Same key, same body The original receipt; no new turn
Same key, different body 409 idempotency_conflict
Another turn is active in the session 409 session_busy (no queue)
Deleted session 410
Capacity exhausted 429 / 503
Answer to a closed question 410 (a conflicting answer is 409)
Deletion progress 202 pending / 200 completed / 500 failed

Terminal turn states include completed, failed, cancelled, timed_out, start_unconfirmed and outcome_unknown.

5. What it can do

  • Long-running turns with one checkpoint for each model step and each tool call. A turn continues after a crash or a redeployment.
  • Parallel tool calls. Results are recorded in the original call order.
  • Human-in-the-loop: the agent calls request_human_input, the run waits, and an answer resumes the same run.
  • Multi-turn sessions through session_id. History is on the server, so another client can restore it.
  • Cancellation, deletion and idle TTL.
  • Owner isolation for each Entra principal or each function key.
  • The existing debug UI polls Durable runs automatically.

6. Typical flow

POST /agents/researcher/chat  (Idempotency-Key: k1)                        → 202 {session_id, run_id, status link}
GET  .../manage/runs/{run_id}                                              → running / question / result
POST .../manage/runs/{run_id}/input/{question_id}                          → only if there is a question
POST /agents/researcher/chat  (x-ms-session-id: <id>, Idempotency-Key: k2) → next turn

Not in v1

Inbound MCP (FF1), Timer and other non-HTTP triggers, workflow/subagent composition, synchronous streaming (chatstream).

@TsuyoshiUshio

Copy link
Copy Markdown
Contributor

Non-blocking observations — not blockers. I am OK to approve this PR as it is. You can handle these items in C2 or later, or you can reply that they are out of scope.

I compared the FRD (head 886734d) with the native Durable Task SDK. I checked the API names on durabletask 1.10.1, which is installed locally; the FRD pins 1.10.0. The FRD already uses many native features: activity RetryPolicy with the retry bridge, Entity serialization, EntityContext.schedule_new_orchestration, delayed signal_entity for deadlines and TTL, timers, external events, fan-out, ContinueAsNew, tags and payload offload. I found four native features that the FRD does not mention. The FRD does not say that it uses them, and it does not say why it does not use them.

1. RetryPolicy.retry_timeout and the whole-run deadline

RetryPolicy has a retry_timeout parameter. The existing create_durable_retry_policy in workflows/native_retry.py does not set it. §4.2 says that the whole-run deadline includes retries. The timer race ends the turn on time, but the FRD does not say that native retries stop at the deadline. A scheduled retry can continue after the turn is timed_out.
Suggestion: set retry_timeout from the remaining run deadline when the runtime schedules each activity. Alternatively, write down why this is not necessary.

2. Native orchestration versioning

The SDK has schedule_new_orchestration(version=...), ctx.version and worker-side version matching. Decision 78 makes cross-deployment compatibility the user's responsibility. The FRD does not say if the runtime uses native versioning to help during rolling deployments, when old and new workers run together.
Suggestion: record whether native versioning is used, for example for the persisted contract version of the runtime. If it is not used, add a short reason.

3. LLM throttling (429 / Retry-After) and activity concurrency

RetryPolicy uses a fixed exponential backoff. It cannot use the Retry-After value from a model provider. The FRD does not say how the runtime handles provider rate limits: wait inside the activity, or wait on a Durable timer and then schedule the call again. The FRD also gives no guidance for host concurrency settings such as maxConcurrentActivityFunctions. Parallel tool fan-out and many sessions can increase provider throttling.
Suggestion: add a short note to §4.7 and §4.8, or add a runbook item in §7.

4. Purge and retention of completed instances

The FRD uses one orchestration for each turn, so instance history grows quickly. The SDK has purge_orchestration and clean_entity_storage, and DTS has retention policies. The FRD mentions purge only as an external risk (§4.5, §4.12). It does not say if the runtime purges completed turn orchestrations, or if operators must configure retention. It also does not say how the Entity storage of a deleted session is cleaned up after the tombstone horizon.
Suggestion: define the owner of retention (runtime or operator) and add it to the Durable runbook in §7.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. My two comments (API summary and Durable-native observations 1-4) are non-blocking. They are FYI and follow-up suggestions only, not change requests.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented but non-blocker to make progress. LGTM.

@larohra
Laveesh Rohra (larohra) merged commit daec873 into feature/durable-agent-loop Sep 25, 2026
16 checks passed
@larohra
Laveesh Rohra (larohra) deleted the larohra/durable-loop-review branch September 25, 2026 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants