Repository navigation
[Bug] ACS events can't fill the fields their OCSF classes require #235
Description
What is broken
ocsf-mapping.json assigns every ACS event an OCSF class, and most of those classes need fields ACS events don't carry: process, device, user, src_endpoint, or one of a required set such as service / dst_endpoint. An exporter that follows the mapping has to invent these values or leave them out, and OCSF validators reject events that leave them out.
Where
specification/v0.1.0/trace/ocsf-mapping.json; docs/spec/trace/events.md; docs/spec/trace/extend_ocsf.md
What the specification says, and what happens instead
ocsf-mapping.json: "v0.1.0 conformance requires that a deployment emitting OCSF for the Trace pillar uses these class UIDs and severity rules verbatim."
events.md, under the OCSF class table: "Required class-specific attributes are populated from the ACS payload."
For most classes the payload has nothing to populate them with. What OCSF 1.9.0, the version #121 pins, requires beyond the base event:
| ACS events | OCSF class | OCSF 1.9.0 requires | What ACS lacks |
|---|---|---|---|
toolCallRequest, toolCallResult |
1007 Process Activity | actor, device, process |
device; a tool call is not an OS process |
sessionStart, sessionEnd, subagentStart, subagentStop |
3002 Authentication | user, plus at least one of service / dst_endpoint |
service and dst_endpoint; user whenever the session has none (user_identity and metadata.user_context are optional, and agentTrigger's scheduled, external_event, a2a_inbound and system triggers can start sessions with no user) |
knowledgeRetrieval, memoryStore, memoryContextRetrieval, preCompact, postCompact |
6005 Datastore Activity | actor, src_endpoint, plus at least one of database / databucket / table |
src_endpoint; store and source names are optional |
agbom/snapshot, agbom/changed (and skillRegister once #63 lands) |
5001 Device Inventory Info | device |
device; an AgBOM describes agent components, not a host |
skillLoad, skillUnload (once #63 lands) |
1005 Module Activity | actor, device, module |
device |
actor can come from metadata.agent_id, which every request carries, and so can the app that 6002 Application Lifecycle needs (prompts and turns), though the mapping doesn't say so. 2004 Detection Finding needs only finding_info, which ACS can fill.
This isn't new with the 1.9.0 pin. process, user and src_endpoint were already class-required in 1.5.0, and device was required on 1007 and 5001 whenever OCSF's host profile applied. OCSF 1.8.0 moved actor and device into the System Activity classes (1007, 1005), actor into Datastore Activity and device into Device Inventory Info, so under 1.9.0 they're required unconditionally.
The official validator (https://schema.ocsf.io/api/v2/validate) confirms it at 1.9.0. Minimal events built only from fields ACS carries fail for every class in the table. 2004 passes, and so does 6002 once the agent fills its app. Our own page fails too: the tool-call example in extend_ocsf.md is rejected with Required attribute "device" is missing., and it fills process with the tool ("name": "database_query", "cmd_line": "tools/call:database_query"). The AgBOM example fills device with the agent ("uid": "agent-123", "type": "AI Agent"). None of the three examples on that page passes; the remaining errors (type_uid, metadata.product, device.type_id) are plain example fixes.
Decisions have a related gap in our own mapping: decision_class.required_fields requires evidences and verdict_id, which OCSF only recommends, and no page says what goes in them. In OCSF, verdict_id is an analyst's verdict on a finding (False Positive, True Positive, Benign, ...). The Guardian's decision fits disposition_id (Allowed, Blocked, ...).
Impact on implementers
An OCSF exporter either leaves these fields out, and validators reject its events, or invents them. Exporters will invent differently (the tool or the agent process as process, the host or the agent as device), so the same deny reads differently in two SIEMs, and detection content written against one deployment misses the other. events.md says the Trace vocabulary "ensures cross-vendor agents and Guardians produce comparable traces"; for these classes it can't yet.
Proposed direction: for every OCSF-required field, ocsf-mapping.json states where the value comes from, either an ACS field or the runtime hosting the Observed Agent (for example device as that host and src_endpoint as its network endpoint), or the event moves to a class ACS can fill, as the #63 decision did for skillLoad. The AI Operation profile in 1.9.0 adds ai_agent, ai_model, delegation and message_context to 1007, 3002, 6005, 6002 and 1005, which gives the agent's identity a native field. The same pass can settle two class-fit questions: prompts and turns sit on 6002, which OCSF describes as "installation, removal, start, stop of an application or service", and the inventory rows could move to 5020 Software Inventory Info, which also requires device but carries an sbom object.
Related: #121 (version pin), #63 (skill classes), #228 (decision fields on the OTel span), #198 (allow class), #234 (examples on other pages).
Current Priority Scope
Feeds conformance evidence
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNeeds triage
Activity
rocklambros commentedon Oct 12, 2026
One more gap of the same kind, for whoever picks this up. OCSF requires
activity_idon every event, and several of our rows still don't set one.activity_idtodayuserMessage,agentResponse,agentTrigger,turnStart,turnEndtoolCallRequest,toolCallResultknowledgeRetrieval,memoryStore,memoryContextRetrieval#258 (for #121) adds
activity_id2 (Collect) to the three 5001 rows, because that was a clear fit. I left these alone on purpose. Picking an id for them is a class-fit call, not a rename. 6002's activities are install, remove, start, stop and similar, and none of them describes a user message or a turn. So this probably gets settled together with the 6002 question above.Status on two other things this issue lists:
type_uid,metadata.product,device.type_id) are in Pin the OCSF mapping to 1.9.0 and use OCSF's class names #258. After it, the deny and AgBOM examples validate clean at 1.9.0. The tool-call example still fails ondevice, which stays here.evidencesandverdict_idparagraph is handled by my [Bug]: acs.decision trace event cannot carry reason_codes, policy_references, cited_provenance_ids, or chain_hash, so replay from the trace alone is not possible #228 PR, which I'll open after Pin the OCSF mapping to 1.9.0 and use OCSF's class names #258 and the [Bug]: otel-mapping.json requires acs.capability on gen_ai.tool.call, but capability is optional in tool-call-request.json #227 PR merge. It replacesverdict_idwithdisposition_idand dropsevidencesfromrequired_fields. One thing I learned doing that:disposition_idisn't defined on Detection Finding by itself. It comes from OCSF's Security Control profile, so the event has to listsecurity_controlinmetadata.profiles, or the validator rejects it.rocklambros commentedon Oct 12, 2026
Status on the
devicegap, the one OCSF error left in our own examples after #258.Where it stands. After #258, the deny example (2004) and the AgBOM example (5001) validate clean at 1.9.0. The tool-call example (1007 Process Activity) still fails with one error:
Required attribute "device" is missing.1007, 1005 and 5001 all requiredeviceunconditionally since OCSF 1.8.0, and no ACS payload carries one.What ACS has to build
devicefrom. The request envelope'smetadatahasplatform,platform_versionandenvironment, but onlyagent_idandsession_idare required. A conformant request can therefore carry nothing describing the host.The 5001 example's workaround. It fills
devicewith the agent itself (uid= the agent id,type_id99 "Other",type"AI Agent"), and the validator accepts that. It works, but it describes the agent, not a device. Two deployments could fill it differently: one with the agent, one with the host.OCSF's AI Operation profile (
ai_operation, in 1.9.0) addsai_agent,ai_model,delegationandmessage_contextto these classes. That gives the agent a proper home. It does not remove thedevicerequirement.Options, for a Spec lead to pick:
deviceis the host running the Observed Agent. The mapping says so, and says to fill it frommetadata.platformandenvironmentwhen present, withtype_id0 (Unknown) when absent. This is honest, but the field will often be empty.deviceis the agent, as the 5001 example already does. The mapping makes that normative (uid=agent_id,type_id99,type"AI Agent"), and the agent's details also go inai_agentunder the AI Operation profile. This is consistent across classes and always fillable, but it stretches what OCSF means by a device.Option 2 is the smallest change that makes every example validate and gives two exporters one answer. It also matches what our 5001 example already does. Whichever option wins, the same rule applies to 1005 (skill load and unload) and 5001. The missing
activity_idon the 6002, 1007 and 6005 rows (my earlier comment here) is the other half of what these rows need.