---
id: WF-PFM-LLM-002
title: Account for a multi-request AI task
trigger: Group model requests under one declared task.
product_area: platform
module: llm
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
implements:
  - CAP-PFM-LLM-003
moves:
  - STATE-PFM-LLM-002
crosses:
  - SVC-PFM-LLM-llm
idempotency: >-
  A supplied replay key is unique within the organization and returns the earlier task without running work;
  unkeyed opens always create another task.
concurrency: >-
  Unique replay keys select one task; closing compares running status and settlement increments may arrive
  after closure.
hops:
  - 'n': 1
    actor_or_service: Consuming feature
    action: Open a declared task with optional subject and replay key.
    anchor: 'services-platform:modules/llm/services/execution/with-llm-execution.ts:withLlmExecution'
    seam: sync
    on_failure: 'Reject unknown keys, missing organization or nested execution.'
    left_inconsistent: No new task is created by a rejected open.
    observer: 'Task status, accumulated settlements and consumer logs.'
    provenance: observed
    source: 'services-platform:modules/llm/catalog/llm-executions.ts:requireLlmExecution'
  - 'n': 2
    actor_or_service: LLM foundation (executions)
    action: 'Persist running task attribution, or return the existing replay record.'
    anchor: 'services-platform:modules/llm/services/persistence/executions.ts:createExecution'
    seam: sync
    on_failure: Do not execute the body if opening fails.
    left_inconsistent: No body work has started.
    observer: 'Task status, accumulated settlements and consumer logs.'
    provenance: observed
    source: 'services-platform:modules/llm/services/execution/with-llm-execution.ts:withLlmExecution'
  - 'n': 3
    actor_or_service: Consuming feature and LLM foundation runtime
    action: Execute the body on its task context and increment totals as requests settle.
    anchor: 'services-platform:modules/llm/services/persistence/executions.ts:addInvocationToExecution'
    seam: sync
    on_failure: Propagate the body error to closing; request failures follow their own accounting path.
    left_inconsistent: 'A derived context loses the task association, leaving its request outside these totals.'
    observer: 'Task status, accumulated settlements and consumer logs.'
    provenance: observed
    source: 'services-platform:modules/llm/services/execution/execution-scope.ts:withExecutionScope'
  - 'n': 4
    actor_or_service: Execution wrapper
    action: Close returned work as completed or thrown work as failed.
    anchor: 'services-platform:modules/llm/services/persistence/executions.ts:closeExecution'
    seam: sync
    on_failure: Expose a successful-body close error; log failed-body close errors and preserve the original failure.
    left_inconsistent: A running task can remain despite completed domain work and later be abandoned.
    observer: 'Task status, accumulated settlements and consumer logs.'
    provenance: observed
    source: 'services-platform:modules/llm/services/execution/with-llm-execution.ts:withLlmExecution'
  - 'n': 5
    actor_or_service: Hourly reconciliation function
    action: Abandon stale running tasks and compare the last seven days of closed totals with settled requests.
    anchor: 'services-platform:modules/llm/services/reconciliation/llm-settlement-sweep.ts:sweepUnsettledInvocations'
    seam: schedule
    on_failure: Log an organization failure and continue the pass.
    left_inconsistent: Detected drift remains uncorrected.
    observer: 'Task status, accumulated settlements and consumer logs.'
    provenance: observed
    source: 'services-platform:modules/llm/services/persistence/executions.ts:listExecutionCounterDrift'
branches:
  - A replay returns its earlier execution without entering the work body.
waits: []
evidence:
  - >-
    services-platform at ad3f6a6: modules/llm/services/execution/with-llm-execution.ts, execution-scope.ts;
    services/persistence/executions.ts, invocations.ts; catalog/llm-executions.ts; db/llm-executions.table.ts;
    services/reconciliation/llm-settlement-sweep.ts;
    tests/integration/lifecycle/executions.integration.spec.js.
controls: [TC-AI-006, TC-AI-007, TC-AVL-001, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-005, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---

# Account for a multi-request AI task

## What It Does

The wrapper creates a task before work and supplies the context needed to associate its requests. A replay key returns the original execution without rerunning its body.

## The Flow

```mermaid
flowchart TD
  H1["Open a declared task with optional subject and replay key."]
  H2["Persist running task attribution, or return the existing replay record."]
  H1 --> H2
  H3["Execute the body on its task context and increment totals as requests settle."]
  H2 --> H3
  H4["Close returned work as completed or thrown work as failed."]
  H3 --> H4
  H5["Abandon stale running tasks and compare the last seven days of closed totals with settled requests."]
  H4 --> H5
```

Each request settlement increments totals inside its own transaction. The wrapper closes after work returns or throws.

## When Something Fails

Close failure can leave completed work marked running; the hourly sweep later abandons it. Failed-body close errors are logged without replacing the original exception.

## Open Design Questions

Consumers must choose replay keys and avoid inferring domain completion from task status alone.
