Hooks (Instrument)¶
Hooks are the instrument pillar of OWASP AOS. They are synchronous interception points in the agent loop where a Guardian Agent receives a payload and returns one of three decisions:
| Decision | Behavior |
|---|---|
allow |
Continue with the original request. |
deny |
Block the request; the agent receives a denial reason. |
modify |
Continue with the modifiedRequest provided by the Guardian. |
Joch's gateways implement every standard AOS hook. The default Guardian Agent is Joch's policy engine; third-party Guardian Agents can substitute or compose.
Hook surface¶
| Hook | Method | Where Joch enforces it |
|---|---|---|
| Agent Trigger | steps/agentTrigger |
Model Router on execution start |
| Tool Call Request | steps/toolCallRequest |
Tool Gateway, MCP Gateway |
| Tool Call Result | steps/toolCallResult |
Tool Gateway, MCP Gateway |
| User Message | steps/message (role: user) |
Model Router |
| Agent Response | steps/message (role: agent) |
Model Router |
| Memory Context Retrieval | steps/memoryContextRetrieval |
Memory service |
| Memory Store | steps/memoryStore |
Memory service |
| Knowledge Retrieval | steps/knowledgeRetrieval |
RAG service |
| MCP Outbound | protocols/MCP (outbound) |
MCP Gateway |
| MCP Inbound | protocols/MCP (inbound) |
MCP Gateway |
| A2A Send | A2A send_message |
A2A broker |
| A2A Stream | A2A stream_message |
A2A broker |
| A2A Cancel | A2A cancel_request |
A2A broker |
| A2A Get Task | A2A get_task |
A2A broker |
| A2A Notification Config | A2A get/set/resubscribe | A2A broker |
Wire format¶
Hook calls are JSON-RPC 2.0. Each request carries a method (e.g., steps/toolCallRequest), an id, and a params object containing:
- the action-specific payload (
trigger,toolCallRequest,toolCallResult,message,memory,knowledgeStep), - a
reasoningfield for the agent's stated rationale, - a
contextblock withagent,session,turnId,stepId,timestamp, and optionaluser/organization.
The Guardian responds with an AOSSuccessResponse containing decision (allow / deny / modify), an optional reason, and (for modify) a modifiedRequest.
Example: tool call request¶
{
"jsonrpc": "2.0",
"method": "steps/toolCallRequest",
"id": "13fa8d6f-8f9f-4d01-ba6b-db99d84d77de",
"params": {
"toolCallRequest": {
"executionId": "69dbf4c3-be33-4694-a9f0-8d3a824c5d5b",
"toolId": "c264f381-10cf-4403-bd11-383014c0fcc6",
"inputs": [
{ "name": "subject", "value": "Refund request for order 12345" },
{ "name": "body", "value": "Customer reports the item never arrived." }
]
},
"reasoning": "Customer is eligible for refund. I will create a Zendesk ticket.",
"context": {
"agent": {
"id": "support-triage",
"name": "Support Triage",
"version": "14",
"provider": { "name": "OpenAI", "url": "https://openai.com/" }
},
"session": { "id": "84c36ebb-83aa-4bc9-8670-7aba4cedc70f" },
"turnId": "69ef57b8-3993-440d-9493-523914f3f149",
"stepId": "9263448a-186a-4c3b-abcf-443feb44a01e",
"timestamp": "2026-05-10T10:34:55.123Z"
}
}
}
A deny response from the Guardian:
{
"jsonrpc": "2.0",
"id": "13fa8d6f-8f9f-4d01-ba6b-db99d84d77de",
"result": {
"decision": "deny",
"reason": "external_write requires approval; approval not granted",
"policyId": "external-send-requires-approval",
"policyVersion": "v3"
}
}
A modify response:
{
"jsonrpc": "2.0",
"id": "13fa8d6f-8f9f-4d01-ba6b-db99d84d77de",
"result": {
"decision": "modify",
"modifiedRequest": {
"inputs": [
{ "name": "subject", "value": "Refund request for order 12345" },
{ "name": "body", "value": "[REDACTED-PII] reported the item never arrived." }
]
},
"reason": "redacted PII in tool argument"
}
}
Where Joch records the decision¶
Every hook decision is recorded as a HookDecision event in the Trace and reflected on the corresponding ToolCall, Approval, or other runtime resource. Auditors can replay any execution and see, at every hook boundary, which Guardian decided what, by which policy version, on which inputs.
Composition¶
Multiple Guardian Agents can be composed:
- any
denyis adeny, modifyoutputs are merged in declared order,allowis the unanimous outcome.
This makes separation of duties practical: a security team's Guardian runs alongside the platform's policy engine without entangling rules.