Skip to content

spec_change: agent_id as the correlation key for OCSF ai_agent.instance_uid (§3.1, §5.2) - #270

Open
rabbidave wants to merge 1 commit into
agentrust-io:mainfrom
rabbidave:agent-state-correlation-key
Open

spec_change: agent_id as the correlation key for OCSF ai_agent.instance_uid (§3.1, §5.2)#270
rabbidave wants to merge 1 commit into
agentrust-io:mainfrom
rabbidave:agent-state-correlation-key

Conversation

@rabbidave

Copy link
Copy Markdown

Closes #269. Companion to the non-normative pointer in #268 (that one is deliberately untouched by this PR).

What this changes:

  • §3.1: makes explicit and normative what §5.3.1 item 3 already implies for gateways (agent_id == "the authenticated workload subject for the current session") — extended here to OCSF-emitting runtime-evidence producers. When such a producer emits an ai_agent-bearing event for a manifest-governed session, ai_agent.instance_uid MUST equal this manifest's agent_id.
  • §5.2: adds optional runtime_correlation_key to the verification result, echoing agent_id so a runtime-evidence consumer doesn't need to re-parse the manifest for the join key. fields_verified is untouched — stays boot-time-only per §7.2.
  • CHANGELOG: [Unreleased] / Added entry per repo convention.

Why instance_uid and not version/charter: both are static across a session (agent code/config revision, durable role doc) — not usable as a per-event join key. They stay useful as secondary context once an instance is already identified.

Worked example (§5.2) uses real output from rabbidave/ws4-secure-design-agentic-systems@1e35ab5: AgentIdentity now feeds OCSF's actual ai_agent object (uid/instance_uid/version/charter/token_fingerprint) instead of the flat, model-conflated agent_uid that implementation used before this fix. The OCSF event block in the example is unmodified output from that code, not hand-authored.

Known open question, not resolved here: agent_id is asked to serve both OCSF's uid (stable) and instance_uid (session-scoped) concepts. §3.1 notes a future revision may split this into two fields if the overload proves to be a problem; this PR doesn't propose that split, flagging it for reviewers instead.

cc @imran-siddique

…ce_uid

Section 5.3.1 already binds agent_id to "the authenticated workload
subject for the current session" for gateway runtime-session binding.
This makes the same binding explicit and normative for OCSF-emitting
runtime-evidence producers: when such a producer emits an ai_agent-
bearing event (e.g. Agent Inventory Info [5050]) for a manifest-governed
session, ai_agent.instance_uid MUST equal this manifest's agent_id.

Verification results gain an optional runtime_correlation_key field
(section 5.2) that echoes agent_id back, so a runtime-evidence consumer
doesn't need to re-parse the manifest to get the join key. fields_verified
is untouched -- it stays boot-time-only per section 7.2; this does not
make the manifest a runtime monitor.

Worked example uses real output from the reference implementation
(rabbidave/ws4-secure-design-agentic-systems@1e35ab5): AgentIdentity now
feeds a proper OCSF ai_agent object (uid/instance_uid/version/charter/
token_fingerprint) instead of the flat, model-conflated agent_uid that
implementation used before.

Does not split agent_id into separate stable/instance fields -- flagged
as an open question for reviewers rather than decided here.

Closes agentrust-io#269.

@imran-siddique imran-siddique 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.

Reviewed this properly against the OCSF schema rather than on the description alone. The problem you identified is real and worth fixing: there is no defined join key between a manifest and OCSF runtime evidence, and picking one is overdue. Your reasoning for choosing instance_uid over version and charter is right, both are static across a session and useless as per-event join keys. Keeping fields_verified boot-time-only per section 7.2 is also correct.

Three things block it as written.

1. The MUST contradicts what OCSF says the field is. From objects/ai_agent.json in ocsf-schema main:

  • uid: "The stable logical identifier for the agent, assigned by the agent's authoritative source"
  • instance_uid: "Identifier for a specific running instance or session of the agent, distinct from the stable logical uid. An instance is a single materialization of the agent."

OCSF makes the distinctness explicit. Section 3.1 immediately above your addition says the /agent/<name>/<instance> path structure is "a convention, not a requirement", so a conformant agent_id may legitimately be stable and carry no instance scope at all. In that configuration your MUST forces a stable identifier into a field OCSF defines as the non-stable one, and the worked example populates uid, instance_uid and session_uid with the same string, which erases the distinction OCSF created the field to express. A consumer can then no longer separate "every run of payments-processor" from "this run".

You flag the overload as a known open question and defer the split. That is the reason not to freeze it as MUST now: if a later revision splits the field, it breaks a normative requirement rather than refining an informative one.

2. The carrier class does not exist in OCSF. Agent Inventory Info [5050] is not in ocsf-schema main. There is no agent_inventory_info.json under events/discovery/, and no occurrence of 5050 anywhere in the repository. The ai_agent object is real, the class you cite as carrying it is not, at least not in core OCSF. If it comes from an extension, say which, because normative text in this spec cannot depend on an event class that core OCSF has not assigned.

3. runtime_correlation_key should be dropped. It is a verbatim copy of agent_id, defined as always present, and explicitly does not affect result or fields_verified. The consumer that reads it has just verified the manifest, so it already holds agent_id. That is zero information gain inside a signed structure, and it introduces a failure mode that does not otherwise exist: two signed copies of the same identity that an implementation can make disagree. The sentence "A verifier that has no runtime-evidence consumers MAY omit populating downstream consumption of this field, but the field itself is always present" is also not usable as normative text, since it permits and forbids in one breath.

On sourcing. The worked example and the reference implementation are both rabbidave/ws4-secure-design-agentic-systems@1e35ab5. One personal implementation is not enough to anchor a MUST that binds every OCSF-emitting producer.

What would land. Either of these works:

  • Make it informative. A crosswalk section stating that where a producer emits ai_agent for a manifest-governed session, instance_uid is the intended join key, with uid carrying the stable manifest-level identity. That is close to the non-normative pointer in #268 and needs none of the above resolved.
  • Keep it normative but scope it to a profile that declares OCSF emission in scope, and resolve stable versus instance first: bind ai_agent.uid to the stable identity and instance_uid to the session-scoped value, which is what OCSF's own definitions ask for. That likely does need the agent_id split you deferred.

Worth raising in the CoSAI WS4 stream either way, since section 3.1 already defers the canonical @context URL to WS4, and an OCSF correlation mapping belongs in the same venue rather than being settled here first.

imran-siddique added a commit that referenced this pull request Aug 4, 2026
Mirrors agentrust-io/trace-spec#120. The rule that normative spec changes
need an organizational sponsor is applied in review but written down
nowhere, so contributors meet it for the first time on their own PR,
after doing the work. #270 is a live example: a normative MUST binding
agent_id to OCSF ai_agent.instance_uid, authored individually, where the
authorship question only surfaced at review.

No change in practice. It also writes down that anyone may propose a
normative change, that proposals are judged on the argument alone, and
that a Maintainer carries the PR when an accepted proposal has no
sponsor, all of which was already true and equally unwritten.

Calls out explicitly that informative crosswalks and mappings to external
schemas need no sponsor, since that is the path a proposal like #270 can
take today.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

spec_change: designate agent_id as the correlation key for OCSF ai_agent.instance_uid (§3.1, §5.2)

2 participants