> ## Content Index
> Fetch the complete content index at: https://devinside.cloud/llms.txt
> Use this file to discover other available public pages before exploring further.

# Delivery is not permission to execute
- URL: https://devinside.cloud/when-an-event-starts-an-agent-delivery-delay-and-ordering-contracts/
- Published: 2026-11-12T15:49:29.000Z
- Updated: 2026-11-13T00:58:23.000Z
- Description: An event announces that an object changed. The application starts an agent. A second delivery of the same event starts another agent. An older event arrives later and starts a third.
- Author: Marcin Borecki
- Tags: Engineering, Events & Durable Work, #plat06, #devinside-review

Historical edition · Sources and examples scoped to 2026-04-30.

*Retrospective edition, scoped to 30 April 2026\. Event envelopes and state transitions are synthetic. The model does not connect to a broker, scheduler or live agent.*

An event announces that an object changed. The application starts an agent. A second delivery of the same event starts another agent. An older event arrives later and starts a third. By the time the first tool executes, the object has changed again, but every run still carries a plausible reason for existing: it received a message.

The missing decision occurs before planning. Is this delivered signal still a valid reason to create or execute work under the current object state and application policy?

Consider an inventory item at version two. Event E1 describes version one. Event E2 describes version two and has a stable identity. A repeated E2 is a duplicate; an E2 with different content is an identity conflict. Another event for the same current version can overlap a pending job without being the same delivery. Those are different situations and deserve different outcomes.

The reader's task is to separate delivery progress from business applicability, then recheck the conditions that can change between admission and execution. A transport watermark can tell us where the consumer has read. It cannot decide which object version is authoritative.

## Give the envelope enough identity to be challenged

A small application envelope can identify event ID, object ID, object version, workflow version, expiry and the requested action. It should also have a stable representation for detecting the same identity with changed content.

```csharp
public sealed record WorkEvent(
    string EventId,
    string ObjectId,
    long ObjectVersion,
    int WorkflowVersion,
    long ExpiresAt,
    string Action);

```

These fields describe a claim about work. They do not grant authority. A payload saying that a user is an administrator should not become trusted context simply because it was delivered through a familiar queue. The admission handler needs its own trusted source and scope policy.

The example uses ordinary application state and a SQLite-style durable ledger. Microsoft Agent Framework had reached its [announced 1.0 milestone earlier in April 2026](https://devblogs.microsoft.com/agent-framework/microsoft-agent-framework-version-1-0/?ref=devinside.cloud), before this edition's context. That gives the agent adapter a contemporary setting; it does not turn broker delivery into exactly-once business execution or supply the admission policy described here.

![A delivered claim does not own the object state](https://devinside.cloud/content/images/2026/11/devinside/v4/PLAT06/envelope-versus-authority.svg)

[Inspect the full diagram ↗](https://devinside.cloud/content/images/2026/11/devinside/v4/PLAT06/envelope-versus-authority.svg)Swipe the drawing to inspect it.

The model lets you deliver an old event, a current event, an exact replay, a conflicting identity and overlapping work. It records the transport position separately from the current object version and the job state. Changing arrival order therefore changes what the consumer observes first without allowing the event to rewrite the object's authority.

## A watermark is not an object version

Suppose E1 has transport position ten and object version one. E2 has transport position twenty and object version two. Receiving E2 first can advance the consumer's observed transport position to twenty. If E1 arrives afterward, its lower object version remains stale even though it is a newly received message in the current process.

A transport cursor may be opaque rather than numeric; the model uses small positions only to make the distinction visible. The application's object version belongs to a different domain. It should not be inferred from the order in which a consumer happened to receive events.

The reverse mistake is also possible. An event with a high transport position can refer to an obsolete object version. A watermark can be useful for replaying a transport stream while remaining insufficient for deciding whether an effect still applies.

The authoritative object record should be consulted under the application's concurrency policy. The event is a reason to investigate or propose work, not permission to treat its snapshot as current forever.

## Duplicate and conflict are different identity outcomes

An exact repeated envelope can be handled idempotently. The ledger returns the previously recorded admission outcome and does not create another job merely because delivery happened twice.

The same event ID with changed content is not harmless replay. If E2 first referred to version two and later refers to version three, the consumer needs to expose that identity conflict. Choosing the later arrival silently would let transport order redefine a supposedly stable operation identity.

![Similar arrivals can mean different things](https://devinside.cloud/content/images/2026/11/devinside/v4/PLAT06/duplicate-conflict-overlap.svg)

[Inspect the full diagram ↗](https://devinside.cloud/content/images/2026/11/devinside/v4/PLAT06/duplicate-conflict-overlap.svg)Swipe the drawing to inspect it.

A different event ID for the same object version is another case. The application may decide that an existing pending job already represents the required work and return Overlap. Another domain might allow several distinct actions on the same version. The correct policy depends on what makes one business obligation unique.

The visual's policy permits one pending job for the selected object version. That is a declared application rule, not a universal property of message brokers or agent frameworks. Its value is that the reader can see why an exact duplicate, a changed identity and a second same-version obligation lead to different decisions.

## Admission is not permanent authorization

After E2 creates a pending job, the item can advance to version three. The pending job still exists as history, but it may no longer be applicable. Claiming it for execution should recheck the current object version and the relevant authority.

A conditional claim can make the intended gate explicit:

```csharp
static string ClaimDecision(Job job, ObjectState current, long now)
{
    if (job.State != "Pending") return "NotPending";
    if (now >= job.ExpiresAt) return "Expired";
    if (!current.Allowed) return "Denied";
    if (job.ObjectVersion != current.Version) return "Superseded";
    return "Claim";
}

```

This is illustrative application logic, not a complete concurrent database implementation. In a real ledger, the transition from Pending to Executing must be protected so two workers cannot both claim the same job. The object and permission checks also need an explicit policy about which changes invalidate an already claimed operation.

The model checks at claim time. It does not promise to recall an external effect after a later permission change. A product requiring continuous authority through emission or commit needs another boundary beyond this admission example.

## Expiry needs an exact edge

Does an event remain valid when its expiry equals the current clock? The worked policy says no: `now >= expires` is expired. That choice should be visible in code and independent expectations, not inferred from a test that only uses obviously old timestamps.

The visual uses a synthetic integer clock. Set now equal to the event's expiry and attempt a claim. The job should stop before an execution attempt. Move the clock earlier in a fresh scenario and the same envelope can be applicable if the other conditions hold.

![The object can change while a job is Pending](https://devinside.cloud/content/images/2026/11/devinside/v4/PLAT06/admission-claim-gap.svg)

[Inspect the full diagram ↗](https://devinside.cloud/content/images/2026/11/devinside/v4/PLAT06/admission-claim-gap.svg)Swipe the drawing to inspect it.

Clock interpretation matters in a real system. An event producer's timestamp, a receiver's clock and a business deadline may not be interchangeable. The application should define which clock governs validity and how uncertainty is handled. A retry should not extend expiry merely because it creates a new delivery time.

Likewise, a periodic scheduler tick does not automatically identify a unique business obligation. Scheduled overlap needs a rule: skip while work is pending, coalesce, queue another run or allow concurrent instances. The timer mechanism cannot choose the business meaning of overlap for you.

## Supersession should preserve the abandoned obligation

Marking an old pending job Superseded can prevent obsolete work, but deleting it immediately may erase the explanation for why the event did not produce an effect. An operator should be able to distinguish invalid work, obsolete work and a failed attempted effect.

That distinction changes the next action. A stale event may require no retry. A denied job may require an authorized actor or changed policy. An expired job may need a new explicitly approved operation. A job whose external effect is Unknown needs reconciliation rather than being reclassified as merely obsolete.

The strongest counterargument is that retaining every skipped event can create a large operational burden. Retention and aggregation policies are legitimate design decisions. They should preserve the evidence required for the service's accountability and recovery promises, rather than flatten every refusal into a generic error counter.

The model retains small decision rows so the causal story remains visible. It is not a claim that a production ledger should keep unbounded payload history or that event text is safe to log without filtering.

## The agent belongs behind the deterministic gate

Once the application has admitted and claimed valid work, an agent can help perform a bounded task. It may inspect evidence, choose among authorized actions or prepare a proposal. It should not be asked to decide whether an old event is current merely by reading its narrative.

Keeping the admission gate outside model reasoning has several benefits. Duplicate handling is reproducible. A denied claim creates no model or tool attempt. A source-version change can invalidate pending work without relying on a prompt instruction. The adapter can evolve while the business identity contract remains testable.

![Transport progress and business applicability are independent](https://devinside.cloud/content/images/2026/11/devinside/v4/PLAT06/watermark-not-version.svg)

[Inspect the full diagram ↗](https://devinside.cloud/content/images/2026/11/devinside/v4/PLAT06/watermark-not-version.svg)Swipe the drawing to inspect it.

A real integration still needs to verify that the framework path receives the intended trusted context and operation identity. The deterministic model is not a substitute for that adapter check. It establishes what the adapter must preserve, rather than pretending a successful function call makes every surrounding decision correct.

## Test the order that is least convenient

Write one hand-calculated sequence before implementing the handler. With the object at version two, deliver E2 at transport position twenty: it creates one Pending job. Deliver E1 for version one at position ten: it is Stale, and the observed transport position remains twenty. Deliver the exact E2 again: it is Duplicate, with the same one job. Change E2's payload while keeping its identity: that is Conflict, not a new pending operation.

Now deliver E3 with another identity but the same object version. Under this example's one-pending-job policy, it is Overlap. Advance the authoritative object to version three before claiming the original job. Claim should return Superseded and leave execution-attempt and effect counts at zero. Those expectations are derived from the declared inputs and rules; they are not measurements of a real broker.

The sequence protects several different boundaries at once without merging their meanings. Transport progress is monotonic in the model, but business applicability comes from the object. Exact replay preserves identity, while changed content exposes conflict. Admission preserves a pending obligation, while claim can discover that the obligation is no longer applicable. A single counter named failed-events would lose most of that explanation.

Deliver the current event before the old one. Repeat the current envelope. Reuse its identity with changed content. Create a pending job, then advance the object or revoke authority before claim. Use an expiry exactly equal to now. Each case should have an independently specified outcome and effect count.

A test that delivers only one current event through a clean queue can prove the happy path while leaving the important contract undefined. The inconvenient sequences are not exotic; retries, delays and object changes are ordinary conditions in event-driven systems.

The next time a message starts an agent run, ask which application fact made that run valid and when that fact is checked again. Delivery is evidence that a signal arrived. Useful, authorized work begins only when the application can explain why the signal still applies.

GO FURTHER

## Inspect the contemporary laboratory.

This is a newly reconstructed historical edition, not a claim of earlier authorship. Later executed experiments, their exact environments and original results are preserved in a separate notebook.

[Open the current laboratory notebook ↗](https://devinside.cloud/lab-notebooks/v4/PLAT06.html)

[Download the current reconstruction sources ↗](https://devinside.cloud/content/files/v4/PLAT06-reconstruction.zip)