AEP has no first-class user_id / subject_id — cross-run behavior audit is awkward
Repo: packages/aep
Problem
AEP is per-run: run_id, trace_id, parent_trace_id, actions[], etc. Nothing on AEPRecord names the human user (or principal / subject) whose intent drove the run.
For a real agent platform serving many users concurrently, "audit all runs by user_lisi over the past week" is one of the most common questions. Today that requires borrowing run_context.delegation_chain[0] as a de-facto user id — which is a convention, not a contract.
Evidence
packages/aep/src/types.ts:
AEPRecordSchema (lines 98-123) — the top-level record has run_id, trace_id, parent_trace_id, repo_commit, runtime_version, model_provider, model_id, policy_bundle_digest, tool_manifest_digest, mcp_server_card_digest, input_refs, output_refs, capability_decisions, actions, verifier_results, budget_ledger, created_at_ms, run_context, signature. No user_id, no subject_id, no principal, no session_id.
RunContextSchema (lines 87-95):
export const RunContextSchema = z.object({
agent_id: z.string().optional(),
agent_version: z.string().optional(),
subagent_id: z.string().optional(),
delegation_chain: z.array(z.string()).default([]),
environment_digest: z.string().optional(),
dependency_lock_digest: z.string().optional(),
});
delegation_chain is meant for parent → child agent lineage, not user attribution. Yet in practice it's the only slot that can hold a user id.
CapabilityDecisionSchema (lines 4-11) has a subject: z.string() field — that's per-action, and its semantic scope isn't defined in the docs. Grep-checking docs/aep-contract.md for subject returns zero mentions.
Impact
- Downstream audit tools guess. Our project relies on
record.run_context.delegation_chain[0] being the user id. If wasmagent's convention shifts (say to always prepend the agent that initiated the run), our behavior rules will silently start attributing actions to the wrong actor.
- Cross-run findings become second-class. open-agent-audit's rules operate per run. To get findings like "this user tried to bypass 5 denied tools in a week", we had to build a separate rule engine on top. If AEP had user_id, aggregation would be natural.
CapabilityDecisionSchema.subject is potentially the right slot, but its semantics aren't documented, so nobody can rely on it.
Proposed fix
Two options, complementary:
Option 1 (small, additive): add a user_id?: string (or subject_id?: string) field to RunContextSchema, distinct from agent_id. Document that this is the human/principal whose intent drove the run, not the agent identity.
export const RunContextSchema = z.object({
agent_id: z.string().optional(),
agent_version: z.string().optional(),
subagent_id: z.string().optional(),
/** Human / principal id whose intent drove this run. */
user_id: z.string().optional(),
/** Optional session id — groups multiple runs by the same user in one product session. */
session_id: z.string().optional(),
delegation_chain: z.array(z.string()).default([]),
environment_digest: z.string().optional(),
dependency_lock_digest: z.string().optional(),
});
Option 2 (bigger): also document the CapabilityDecisionSchema.subject semantics — is it the user, the agent, or the caller of the current action? Right now the docs are silent.
Bonus: if the adapter (open-agent-audit/packages/adapters/src/aep-v0_2.ts) propagates user_id into every canonical event's actor field, downstream rule engines get user attribution for free.
We'd send a PR happily; want to align on which field naming (user_id vs subject_id vs principal_id) fits the wider WasmAgent ecosystem before we do.
Filed by: CATL Ariba Joule integration team. Behavior audit rules like "user X tried the same denied tool 5 times across 3 sessions" require a stable user attribution key across records; we borrow delegation_chain[0] today but would prefer a real field.
AEP has no first-class
user_id/subject_id— cross-run behavior audit is awkwardRepo:
packages/aepProblem
AEP is per-run:
run_id,trace_id,parent_trace_id,actions[], etc. Nothing onAEPRecordnames the human user (or principal / subject) whose intent drove the run.For a real agent platform serving many users concurrently, "audit all runs by user_lisi over the past week" is one of the most common questions. Today that requires borrowing
run_context.delegation_chain[0]as a de-facto user id — which is a convention, not a contract.Evidence
packages/aep/src/types.ts:AEPRecordSchema(lines 98-123) — the top-level record hasrun_id,trace_id,parent_trace_id,repo_commit,runtime_version,model_provider,model_id,policy_bundle_digest,tool_manifest_digest,mcp_server_card_digest,input_refs,output_refs,capability_decisions,actions,verifier_results,budget_ledger,created_at_ms,run_context,signature. Nouser_id, nosubject_id, noprincipal, nosession_id.RunContextSchema(lines 87-95):delegation_chainis meant for parent → child agent lineage, not user attribution. Yet in practice it's the only slot that can hold a user id.CapabilityDecisionSchema(lines 4-11) has asubject: z.string()field — that's per-action, and its semantic scope isn't defined in the docs. Grep-checkingdocs/aep-contract.mdforsubjectreturns zero mentions.Impact
record.run_context.delegation_chain[0]being the user id. If wasmagent's convention shifts (say to always prepend the agent that initiated the run), our behavior rules will silently start attributing actions to the wrong actor.CapabilityDecisionSchema.subjectis potentially the right slot, but its semantics aren't documented, so nobody can rely on it.Proposed fix
Two options, complementary:
Option 1 (small, additive): add a
user_id?: string(orsubject_id?: string) field toRunContextSchema, distinct fromagent_id. Document that this is the human/principal whose intent drove the run, not the agent identity.Option 2 (bigger): also document the
CapabilityDecisionSchema.subjectsemantics — is it the user, the agent, or the caller of the current action? Right now the docs are silent.Bonus: if the adapter (
open-agent-audit/packages/adapters/src/aep-v0_2.ts) propagatesuser_idinto every canonical event'sactorfield, downstream rule engines get user attribution for free.We'd send a PR happily; want to align on which field naming (
user_idvssubject_idvsprincipal_id) fits the widerWasmAgentecosystem before we do.Filed by: CATL Ariba Joule integration team. Behavior audit rules like "user X tried the same denied tool 5 times across 3 sessions" require a stable user attribution key across records; we borrow
delegation_chain[0]today but would prefer a real field.