What is broken
The rule that establishes the canonical session Intent covers only the case where sessionStart carries one. It says nothing about the case where sessionStart omits it, and sessionStart has no required fields at all.
session-start.json states the rule from one end:
Optional Intent established at session start. Same shape as Intent inside agentTrigger. When present, the Guardian MUST treat this as the canonical session Intent: any later agentTrigger that attempts to establish a different Intent MUST be rejected, and Intent.parsed MUST NOT be mutable except via the intent_extension mechanism in ask-details.json.
agent-trigger.json describes the same field from the other end, and describes it as something that happened elsewhere:
Optional Intent registered at session start (IBAC adopters populate)
So agentTrigger.intent presents itself as a copy of something registered at sessionStart, while sessionStart.intent is optional and agentTrigger requires only trigger_type. When no sessionStart Intent exists, neither schema says whether an agentTrigger Intent establishes the canonical one, whether the first one wins, or whether the session simply has none.
Where
specification/v0.1.0/hooks/session-start.json, specification/v0.1.0/hooks/agent-trigger.json
What the specification says, and what happens instead
Two conformant Guardians reach opposite conclusions from identical wire traffic.
One reads the rule as establishing precedence generally: the first Intent to arrive becomes canonical, wherever it arrives from, so a second agentTrigger proposing a different Intent is rejected. The other reads the rule as conditional on sessionStart: no sessionStart Intent means no canonical Intent was ever established, so every agentTrigger Intent is fresh and none can be rejected for conflicting.
Both readings are defensible from the text. The first preserves the rule's evident purpose. The second is what the words actually say, since the MUST is scoped by "When present."
This is not a corner case. trigger_type enumerates user_message, scheduled, external_event, a2a_inbound, and system. Four of those five wake an agent with no interactive session opening, which is precisely the path where no sessionStart Intent exists and precisely the path where no human is present to notice an Intent that is wider than it should be.
Impact on implementers
Intent is the carrier for capability grants. An undefined rule about what establishes it is an undefined rule about what an agent is authorized to do, on the activation paths that run unattended.
The second reading is the dangerous one and it is the more literal. If no canonical Intent is ever established, then the rejection rule never fires, and an agent woken by a scheduled trigger can present a different Intent on every activation with nothing to compare it against. The intent_extension mechanism in ask-details.json exists to control widening through an approved path, and it is bypassed entirely when there is no baseline to widen from.
A Guardian that takes the first reading and a client built against the second will also disagree in production rather than at handshake. The client sends a second agentTrigger Intent expecting it to be accepted, the Guardian rejects it as a conflict, and nothing in the handshake surfaced the disagreement beforehand.
Direction: say what establishes the canonical Intent when sessionStart does not, and align the two schema descriptions so they describe the same mechanism rather than each pointing at the other. Whether the answer is first-wins, sessionStart-only, or no-canonical-Intent is a policy question, and any of the three is better than the current silence.
Verified against PR #21's head, which leaves both schemas as quoted.
Current Priority Scope
Feeds conformance evidence
What is broken
The rule that establishes the canonical session Intent covers only the case where
sessionStartcarries one. It says nothing about the case wheresessionStartomits it, andsessionStarthas no required fields at all.session-start.jsonstates the rule from one end:agent-trigger.jsondescribes the same field from the other end, and describes it as something that happened elsewhere:So
agentTrigger.intentpresents itself as a copy of something registered atsessionStart, whilesessionStart.intentis optional andagentTriggerrequires onlytrigger_type. When nosessionStartIntent exists, neither schema says whether anagentTriggerIntent establishes the canonical one, whether the first one wins, or whether the session simply has none.Where
specification/v0.1.0/hooks/session-start.json,specification/v0.1.0/hooks/agent-trigger.jsonWhat the specification says, and what happens instead
Two conformant Guardians reach opposite conclusions from identical wire traffic.
One reads the rule as establishing precedence generally: the first Intent to arrive becomes canonical, wherever it arrives from, so a second
agentTriggerproposing a different Intent is rejected. The other reads the rule as conditional onsessionStart: nosessionStartIntent means no canonical Intent was ever established, so everyagentTriggerIntent is fresh and none can be rejected for conflicting.Both readings are defensible from the text. The first preserves the rule's evident purpose. The second is what the words actually say, since the MUST is scoped by "When present."
This is not a corner case.
trigger_typeenumeratesuser_message,scheduled,external_event,a2a_inbound, andsystem. Four of those five wake an agent with no interactive session opening, which is precisely the path where nosessionStartIntent exists and precisely the path where no human is present to notice an Intent that is wider than it should be.Impact on implementers
Intent is the carrier for capability grants. An undefined rule about what establishes it is an undefined rule about what an agent is authorized to do, on the activation paths that run unattended.
The second reading is the dangerous one and it is the more literal. If no canonical Intent is ever established, then the rejection rule never fires, and an agent woken by a scheduled trigger can present a different Intent on every activation with nothing to compare it against. The
intent_extensionmechanism inask-details.jsonexists to control widening through an approved path, and it is bypassed entirely when there is no baseline to widen from.A Guardian that takes the first reading and a client built against the second will also disagree in production rather than at handshake. The client sends a second
agentTriggerIntent expecting it to be accepted, the Guardian rejects it as a conflict, and nothing in the handshake surfaced the disagreement beforehand.Direction: say what establishes the canonical Intent when
sessionStartdoes not, and align the two schema descriptions so they describe the same mechanism rather than each pointing at the other. Whether the answer is first-wins,sessionStart-only, or no-canonical-Intent is a policy question, and any of the three is better than the current silence.Verified against PR #21's head, which leaves both schemas as quoted.
Current Priority Scope
Feeds conformance evidence