Skip to content

Question: AuditEvent seq scope for cross-producer ordering with orchestrator #198

Description

@initializ-mk

Context

The agent-orchestrator (initializ/agent-orchestrator) is wiring up its own audit-event emit path onto the same NATS JetStream stream (AUDIT_EVENTS / subject auditEvent) that Forge agents publish to:

  • ORCH-2 (initializ/agent-orchestrator#22) ships the orchestrator's AuditEvent envelope + NATS publisher, modeled on runtime.AuditEvent.
  • ORCH-3 (initializ/agent-orchestrator#24) hooks the six workflow lifecycle events (workflow_started, workflow_step_*, workflow_complete, workflow_cancelled).
  • ORCH-7 (initializ/agent-orchestrator#26) propagates X-Workflow-Id / X-Workflow-Execution-Id / X-Workflow-Step-Id so a downstream agent's audit events share the workflow's identity.

For a single workflow run, the audit stream then contains events from N producers: the orchestrator (1) and each agent invoked as a step (1 per step).

Question

What scope does Forge's seq field use?

The orchestrator scopes its seq per workflow_execution_id (counter starts at 1 for the first event of the run, advances by 1 per subsequent event). If Forge does the same — keying its sequencer on workflow_execution_id once the FWS-2 headers are present — then the seqs collide on the wire: both producers emit events with seq=1, 2, 3... for the same workflow_execution_id.

Looking for confirmation of one of:

  1. Per-invocation — Forge's seq is monotonic for the lifetime of one A2A call (one orchestrator dispatch). New invocation → seq restarts at 1. Doesn't collide with orchestrator across invocations, but two parallel agent calls for the same execution still collide with each other.
  2. Per-execution — Forge's seq is monotonic per workflow_execution_id. Collides directly with orchestrator's seq for the same execution.
  3. Per-agent-process — Forge's seq counts events emitted by this agent process since startup, regardless of which workflow they belong to. Never collides with orchestrator within a single execution, but seq isn't useful for in-run gap detection.

Why it matters

The orchestrator's docstring on its Sequencer says "monotonic per WorkflowExecutionID — starts at 1 for the first event of a run." If Forge uses the same scope (option 2), a naive consumer that orders or dedupes by (workflow_execution_id, seq) will see duplicates / gaps for every multi-producer workflow.

Both sides need to agree on:

  • The seq scope (so the docstrings are consistent across producers).
  • The partition key for consumers — almost certainly (workflow_execution_id, entity_type, entity_id, seq) rather than (workflow_execution_id, seq). Worth nailing down which fields disambiguate.
  • Whether to add an explicit producer / source field to the envelope so consumers don't have to infer the entity-vs-producer mapping. Could land in either codebase or both.

Cross-refs

  • initializ/agent-orchestrator#22 — orchestrator audit publisher (ORCH-2)
  • initializ/agent-orchestrator#24 — workflow lifecycle audit events (ORCH-3)
  • initializ/agent-orchestrator — paired orchestrator-side follow-up to tighten the docstring and (optionally) add a producer field; link added in a follow-up comment.
  • forge#185 — X-Workflow-Id header contract split

Asks

  1. Confirm the seq scope Forge uses today (or plans to use once the FWS-2 contract is fully wired).
  2. Confirm the consumer-side partition key — what does the security service partition on before checking seq?
  3. Opinion on adding a producer field to the envelope so the contract is explicit on both sides.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions