Agent Runtime Semantics

Harmovela Agent Runtime Semantics

> Status: draft. Part of the Harmovela 0.2 runtime-semantics profile.

Purpose

Define recommended envelope metadata fields and event types for agent-runtime concerns that go beyond transport, session, subscription, and task lifecycle: belief revision, freshness and validity, delegation and handoff, interruption and cancellation safety, and provenance and trust.

All additions are optional. No existing required fields change. All fields fall under the envelope additionalProperties: true policy.

Terminology And Normative Language

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

Normative requirements use RFC 2119 keywords. Guidance sections that do not use these keywords are non-normative and provided for implementation convenience only.

Epistemic Metadata

Fields

FieldTypeValuesDescription
belief_statusstring"asserted", "retracted", "revised", "contradicted", "unknown"Epistemic relationship of this event to prior knowledge
belief_scopestring"fact", "inference", "observation", "preference", "hypothesis"Category of the assertion
confidencenumber0.0 – 1.0Optional producer-assigned confidence

Events

#### belief.revised

Emitted when an agent discovers an earlier belief was incorrect and publishes the corrected state.

{
  "type": "belief.revised",
  "belief_status": "revised",
  "belief_scope": "fact",
  "confidence": 0.95,
  "causation_id": "evt_original_assertion",
  "payload": {
    "previous": "The project deadline is 2026-07-15",
    "corrected": "The project deadline is 2026-07-22",
    "reason": "stakeholder extended the schedule"
  }
}

#### belief.conflict.detected

Emitted when multiple sources assert contradictory claims about the same subject.

{
  "type": "belief.conflict.detected",
  "belief_status": "contradicted",
  "payload": {
    "subject": "current temperature in Tokyo",
    "claims": [
      {"source": "weather_service_a", "value": "22C", "confidence": 0.9},
      {"source": "weather_service_b", "value": "25C", "confidence": 0.85}
    ],
    "resolution_hint": "prefer_higher_confidence"
  }
}

Normative Requirements

Freshness And Validity

Fields

Distinct from expires_at (which governs event delivery lifetime). These fields describe when the *asserted content* becomes stale.

FieldTypeDescription
valid_fromRFC 3339The point in time from which the assertion is considered valid
valid_untilRFC 3339The point in time after which the assertion should be considered stale
stale_afterISO 8601 durationRelative staleness duration from created_at (alternative to valid_until)
refresh_hintURIWhere to obtain a more current version of this assertion

Events

#### freshness.expired

Emitted by a runtime or observer when it detects cached state has exceeded its validity window.

{
  "type": "freshness.expired",
  "causation_id": "evt_cached_snapshot",
  "payload": {
    "resource": "context:file_tree",
    "cached_at": "2026-07-10T09:00:00Z",
    "valid_until": "2026-07-10T09:05:00Z",
    "detected_at": "2026-07-10T09:06:00Z"
  }
}

#### freshness.window.changed

Emitted when a previously declared validity window is shortened or extended.

{
  "type": "freshness.window.changed",
  "payload": {
    "resource": "memory:user_preferences",
    "previous_valid_until": "2026-07-10T10:00:00Z",
    "new_valid_until": "2026-07-10T09:30:00Z",
    "reason": "user manually updated preferences"
  }
}

Normative Requirements

Delegation And Handoff

Fields

FieldTypeDescription
delegated_bystringIdentifier of the delegating agent or runtime
delegated_tostringIdentifier of the accepting agent or runtime
parent_task_idstringThe delegating task; establishes parent-child relationship
handoff_tokenstringOpaque token proving ownership transfer

Events

#### delegation.requested

{
  "type": "delegation.requested",
  "delegated_by": "agent:planner",
  "delegated_to": "agent:worker",
  "parent_task_id": "task_01",
  "task_id": "task_02",
  "payload": {
    "work_description": "Index all PDFs in the documents directory",
    "deadline": "2026-07-10T12:00:00Z",
    "priority": "normal"
  }
}

#### delegation.accepted

{
  "type": "delegation.accepted",
  "delegated_by": "agent:planner",
  "delegated_to": "agent:worker",
  "parent_task_id": "task_01",
  "task_id": "task_02"
}

#### delegation.rejected

{
  "type": "delegation.rejected",
  "delegated_by": "agent:planner",
  "delegated_to": "agent:worker",
  "parent_task_id": "task_01",
  "task_id": "task_02",
  "payload": {
    "reason": "worker is at capacity",
    "retry_after": "2026-07-10T12:05:00Z"
  }
}

#### delegation.handoff.completed

Emitted when ownership transfer is acknowledged by both sides.

{
  "type": "delegation.handoff.completed",
  "delegated_by": "agent:planner",
  "delegated_to": "agent:worker",
  "parent_task_id": "task_01",
  "task_id": "task_02",
  "handoff_token": "ht_abc123"
}

#### delegation.escalated

Emitted when a delegated task is escalated to a supervisor or higher-authority agent.

{
  "type": "delegation.escalated",
  "delegated_by": "agent:worker",
  "delegated_to": "agent:supervisor",
  "parent_task_id": "task_01",
  "task_id": "task_02",
  "payload": {
    "reason": "task exceeds worker capability",
    "progress_so_far": 0.3
  }
}

Normative Requirements

Handoff Token Semantics

A handoff_token is an opaque bearer token that proves ownership transfer from the delegating agent to the delegate. It is emitted on delegation.handoff.completed and MUST be validated by any runtime that receives a status query or subsequent delegation event for the transferred task.

#### Token Structure

Handoff tokens are opaque strings as transmitted on the wire. Implementations that produce structured tokens SHOULD encode the following claims:

ClaimRequiredDescription
issyesIssuer identifier (the delegating agent, matching delegated_by on the event)
subyesDelegate identifier (the receiving agent, matching delegated_to on the event)
task_idyesThe task whose ownership is being transferred
parent_task_idyesThe parent delegating task
iatyesIssued-at timestamp (RFC 3339)
expyesExpiration timestamp (RFC 3339). Tokens without expiry MUST be rejected.
jtiyesUnique token identifier (nonce) for replay protection
signoCryptographic signature. Advanced feature reserved for harmovela.security.v2 profile work (see below).

#### Validation Requirements

A runtime receiving a handoff_token MUST perform the following checks before accepting it as proof of ownership transfer:

1. Issuer match: The iss claim MUST match the delegated_by field on the accompanying delegation.handoff.completed event. 2. Delegate match: The sub claim MUST match the delegated_to field on the event. 3. Task binding: The task_id and parent_task_id claims MUST match the corresponding fields on the event. 4. Expiry check: The current time MUST be before the exp claim. Expired tokens MUST be rejected. 5. Replay protection: The jti claim MUST NOT have been observed by this runtime before. Runtimes SHOULD maintain a token replay cache with a retention period not shorter than the maximum token expiry window. 6. Timeliness: The iat claim MUST NOT be in the future (with a reasonable clock-skew tolerance of up to 60 seconds). 7. Opaqueness: Consumers that cannot validate token internals MUST treat the token as opaque and MUST NOT rely on it for authorization decisions beyond "the delegating runtime issued this token."

#### Delegation Event Binding

The handoff_token exists only within the context of a specific delegation flow:

#### Future Profile Work

The following handoff token features are reserved for future security profiles and are NOT part of the current harmovela.runtime-semantics.v1 specification:

Interruption And Cancellation Safety

Fields

FieldTypeDescription
checkpoint_idstringIdentifier for saved execution state
checkpoint_atRFC 3339Timestamp when the checkpoint was saved
interruption_policystring"save_and_stop", "drain_then_stop", "force_stop"
compensation_idstringLinks a compensation task to the task it compensates for

Events

#### Interruption Lifecycle

interruption.requested
      │
      ▼
interruption.acknowledged
      │
      ├──▶ interruption.saved ──▶ (later) interruption.resumed ──▶ task.progress
      │
      └──▶ interruption.cancelled

#### interruption.requested

{
  "type": "interruption.requested",
  "task_id": "task_01",
  "interruption_policy": "save_and_stop",
  "payload": {
    "reason": "maintenance window approaching",
    "grace_period_ms": 5000
  }
}

#### interruption.acknowledged

{
  "type": "interruption.acknowledged",
  "task_id": "task_01",
  "interruption_policy": "save_and_stop"
}

#### interruption.saved

{
  "type": "interruption.saved",
  "task_id": "task_01",
  "checkpoint_id": "ckpt_task_01_20260710_100500",
  "checkpoint_at": "2026-07-10T10:05:00Z",
  "payload": {
    "bytes_saved": 4096,
    "location": "s3://checkpoints/task_01/ckpt_20260710_100500"
  }
}

#### interruption.resumed

{
  "type": "interruption.resumed",
  "task_id": "task_01",
  "checkpoint_id": "ckpt_task_01_20260710_100500",
  "causation_id": "evt_interruption_saved"
}

#### interruption.cancelled

Emitted when an interrupted task is terminated rather than resumed.

{
  "type": "interruption.cancelled",
  "task_id": "task_01",
  "causation_id": "evt_interruption_requested",
  "payload": {
    "reason": "maintenance extended; task will be recreated",
    "checkpoint_id": "ckpt_task_01_20260710_100500"
  }
}

#### Compensation Events

#### compensation.requested

{
  "type": "compensation.requested",
  "task_id": "task_comp_01",
  "compensation_id": "task_original_01",
  "payload": {
    "original_task": "task_01",
    "reason": "partial effects must be rolled back",
    "description": "Delete any files created during the aborted indexing run",
    "deadline": "2026-07-10T11:00:00Z"
  }
}

#### compensation.completed

{
  "type": "compensation.completed",
  "task_id": "task_comp_01",
  "compensation_id": "task_original_01",
  "payload": {
    "files_deleted": 14,
    "bytes_reclaimed": 204800
  }
}

Normative Requirements

Provenance

Fields

FieldTypeDescription
evidence_chainarray of objects with source (string) and id (string)Ordered list of events and sources that contributed to this assertion, from origin to immediate predecessor
source_truststring"verified", "attested", "unverified", "signed"
attestation_countnumberNumber of independent verifications of this assertion
data_provenanceURILink to a machine-readable provenance document

The evidence_chain field extends causation_id (which identifies only the single immediately preceding event) into a multi-hop lineage:

{
  "evidence_chain": [
    {"source": "sensor:temperature_a", "id": "evt_raw_reading"},
    {"source": "agent:analytics", "id": "evt_aggregated"},
    {"source": "agent:reporter", "id": "evt_current_assertion"}
  ],
  "causation_id": "evt_aggregated"
}

Events

#### provenance.attestation.added

{
  "type": "provenance.attestation.added",
  "causation_id": "evt_original_assertion",
  "payload": {
    "attestor": "agent:verifier",
    "method": "cross_reference",
    "result": "confirmed"
  }
}

#### provenance.attestation.revoked

{
  "type": "provenance.attestation.revoked",
  "causation_id": "evt_attestation_added",
  "payload": {
    "attestor": "agent:verifier",
    "reason": "cross-reference source has been retracted"
  }
}

#### provenance.chain.truncated

Emitted when a runtime detects that earlier links in an evidence chain are no longer available (e.g., due to retention policy).

{
  "type": "provenance.chain.truncated",
  "causation_id": "evt_original_assertion",
  "payload": {
    "earliest_available": "evt_aggregated",
    "missing_from": "evt_raw_reading",
    "reason": "events before 2026-07-01 have been purged per retention policy"
  }
}

Normative Requirements

Relationship To Other Specs

SpecRelationship
task-lifecycle.mdDelegation, interruption, and compensation events compose with the task state machine
session.mdSession close SHOULD trigger interruption with policy save_and_stop for all active tasks
subscription.mdConsumers MAY subscribe to belief.*, freshness.*, delegation.*, interruption.*, compensation.*, and provenance.*
delivery.mdCheckpoint events SHOULD use at_least_once delivery
security.mdsource_trust: "signed" verification and handoff_token validation MAY require identity/auth metadata
error-model.mdError payloads for delegation rejection, interruption failure, and provenance verification failure MUST follow the standard error model

Field Summary

DomainFields Added
Epistemicbelief_status, belief_scope, confidence
Freshnessvalid_from, valid_until, stale_after, refresh_hint
Delegationdelegated_by, delegated_to, parent_task_id, handoff_token
Interruptioncheckpoint_id, checkpoint_at, interruption_policy, compensation_id
Provenanceevidence_chain, source_trust, attestation_count, data_provenance

All fields are optional envelope properties. All event types follow the domain.object.action naming convention. No existing required fields or event types change.

Profile-Level Conditional Requiredness

All runtime-semantics fields are envelope-level optional properties with additionalProperties: true enabled. When a session declares a profile during capability negotiation, specific fields become conditionally REQUIRED or SHOULD-level based on the event type and profile scope.

Profile: harmovela.runtime-semantics.v1

When this profile is negotiated, the following fields become conditionally required:

Event typeConditionally required fieldsLevel
belief.revisedbelief_status, belief_scopeREQUIRED
belief.conflict.detectedbelief_statusREQUIRED
freshness.expiredvalid_until or stale_afterREQUIRED (at least one)
freshness.window.changedvalid_until (as new_valid_until in payload)REQUIRED
delegation.requesteddelegated_by, delegated_to, parent_task_idREQUIRED
delegation.accepteddelegated_by, delegated_to, parent_task_idREQUIRED
delegation.rejecteddelegated_by, delegated_to, parent_task_idREQUIRED
delegation.handoff.completeddelegated_by, delegated_to, parent_task_id, handoff_tokenREQUIRED
delegation.escalateddelegated_by, delegated_to, parent_task_idREQUIRED
interruption.requestedinterruption_policyREQUIRED
interruption.savedcheckpoint_id, checkpoint_atREQUIRED
interruption.resumedcheckpoint_idREQUIRED
compensation.requestedcompensation_idREQUIRED
compensation.completedcompensation_idREQUIRED
provenance.attestation.addedevidence_chain or causation_idREQUIRED (at least one)

Non-event-specific envelope fields (delegated_by, delegated_to, parent_task_id, checkpoint_id, checkpoint_at, interruption_policy, compensation_id) are REQUIRED only on the event types listed above. They MAY be present on other event types but carry no normative weight.

Profile: harmovela.coordination.v1

When this profile is negotiated in addition to harmovela.runtime-semantics.v1, the following additional constraints apply:

Event typeConditionally required fieldsLevel
delegation.handoff.completedhandoff_token expiry MUST be checked (see Handoff Token Semantics)REQUIRED
task.cancelled (child)causation_id MUST reference parent task.cancelled or task.cancelled eventREQUIRED
Any task event on a task with parent_task_idParent task MUST exist and MUST NOT be in terminal state unless this event itself is a terminal transition (cancellation propagation)REQUIRED

Additionally, delegated_by, delegated_to, and parent_task_id on delegation events become REQUIRED (enforced at the runtime-semantics.v1 level above). The coordination profile adds orchestration-level validation (cancellation cascade, parent-child terminal ordering) that builds on these fields.

Profile: harmovela.security.v1

When this profile is negotiated, source_trust: "signed" assertions on provenance events MUST carry a verifiable signature. The handoff_token validation checks defined in the Handoff Token Semantics section become REQUIRED rather than RECOMMENDED.

Conformance Validation

Implementations MAY validate conditional requiredness at envelope validation time by examining the negotiated profile set. A fixture that passes core envelope validation (HARMOVELA-C0) MAY fail profile-level validation if conditionally required fields are missing. Conformance fixtures for profile validation are tagged with the corresponding profile identifier in the manifest.

Payload Schemas

Structured payload validation is defined in the shared payloads schema:

schemas/harmovela-payloads.schema.json (https://schemas.axisrobo.com/harmovela-payloads.v0.1.schema.json)

The schema uses if/then discriminator blocks keyed on the envelope type field to validate payloads for the following event types:

FamilyValidated types
Contextcontext.invalidated, context.updated, context.snapshot.requested, context.snapshot.ready
Memorymemory.fact.invalidated, memory.fact.added, memory.fact.updated
Beliefbelief.revised, belief.conflict.detected
Freshnessfreshness.expired, freshness.window.changed
Delegationdelegation.requested, .accepted, .rejected, .handoff.completed, .escalated
Interruptioninterruption.requested, .acknowledged, .saved, .resumed, .cancelled
Compensationcompensation.requested, .completed
Provenanceprovenance.attestation.added, .revoked, .chain.truncated

Conformance tests in TypeScript and Python validate payloads against this schema.