Wake gate
Decide whether an event should wake a sleeping agent now, later, or not at all.
Decide whether an event should wake a sleeping agent now, later, or not at all. Pattern: intent_routing. Model: jev-1.13.0. Outage rule: review.
When to use it
- A long-running agent sleeps until something relevant happens, and waking it on every event costs a full LLM turn.
- Events arrive from chat, email, tickets or webhooks, and most of them have nothing to do with what the agent waits for.
When not to use it
- The agent waits for one exact signal, such as a webhook with a known id or a status field changing. Match it in code.
- Deciding needs the agent's full history and planning. Wake the agent and let it decide.
Questions
| Id | Type | Asks | Answers | Gating |
|---|---|---|---|---|
wake_decision | choice | An agent is asleep and waiting for something specific. Given this new event, what should happen to the agent? | wake, not_yet, unrelated, unclear | yes |
Reading the result
- Routes:
wakewakes the agent now,sleepkeeps it asleep (the event is related but not the trigger yet),ignoredrops the event.unclearand every non-auto action wake the agent, so the gate never hides an event it is unsure about. - Outage rule:
onUnavailableisreview. During a System One outage every event comes back asreview. Treat that as wake, with a note that the gate was unavailable, or put the event in a queue a person reads. Never drop events during an outage. - Skip limit: count consecutive
sleepandignoredecisions per agent in your code, and wake the agent anyway after a limit (for example 50 events or 6 hours, whichever comes first). Counting stays in code, since models are weak at it, and the limit makes sure a wrong gate cannot keep an agent asleep forever. - Keep
agent.goalandagent.waiting_forshort and specific. The gate is only as good as that description.
Spec
Save it as bandwise/sets/wake-gate.json and edit it for your data.
{
"schemaVersion": 1,
"model": "jev-1.13.0",
"input": {
"schema": {
"type": "object",
"required": [
"agent",
"event"
],
"properties": {
"agent": {
"type": "object",
"required": [
"goal",
"waiting_for"
],
"properties": {
"goal": {
"type": "string",
"maxLength": 1000
},
"waiting_for": {
"type": "string",
"maxLength": 1000
}
}
},
"event": {
"type": "object",
"required": [
"source",
"content"
],
"properties": {
"source": {
"type": "string"
},
"from": {
"type": "string"
},
"content": {
"type": "string",
"maxLength": 8000
}
}
}
}
}
},
"stages": [
{
"id": "gate",
"questions": {
"wake_decision": {
"type": "choice",
"instructions": {
"question": "An agent is asleep and waiting for something specific. Given this new event, what should happen to the agent?",
"agent_goal": "`agent.goal`",
"agent_waiting_for": "`agent.waiting_for`",
"new_event": "`event`"
},
"criteria": {
"wake": "The event is what the agent waits for, or it changes the agent's goal, so the agent should act now.",
"not_yet": "The event is about the agent's goal but is not the thing it waits for yet, such as progress or a partial answer.",
"unrelated": "The event has nothing to do with the agent's goal.",
"unclear": "The event could matter, but it does not give enough to tell."
},
"meta": {
"label": "Wake the agent"
}
}
}
}
],
"policies": {
"wake_decision": {
"type": "choice",
"gating": true,
"thresholds": {
"high": 0.7,
"medium": 0.4
},
"actions": {
"high": {
"kind": "auto"
},
"medium": {
"kind": "review"
},
"low": {
"kind": "fallback",
"config": {
"kind": "value",
"value": "wake"
}
}
}
}
},
"routes": [
{
"when": {
"q": "wake_decision",
"eq": "wake"
},
"output": "wake"
},
{
"when": {
"q": "wake_decision",
"eq": "not_yet"
},
"output": "sleep"
},
{
"when": {
"q": "wake_decision",
"eq": "unrelated"
},
"output": "ignore"
}
],
"defaultRoute": "wake",
"savings": {
"comparatorModel": "claude-haiku-4-5",
"estOutputTokensPerQuestion": 30,
"kind": "decision"
},
"onUnavailable": "review"
}Example states
The expected outcome is what a person would decide. It is not a recorded model answer.
The approval arrives
Expected: wake: this is what the agent waits for.
{
"agent": {
"goal": "Ship the v2 billing export once finance approves the column list.",
"waiting_for": "Finance approval of the export columns, from anyone on the finance team."
},
"event": {
"source": "chat",
"from": "priya (finance)",
"content": "Columns look good to me, approved. Go ahead with the export."
}
}Progress, not the answer
Expected: sleep: related, but approval has not happened.
{
"agent": {
"goal": "Ship the v2 billing export once finance approves the column list.",
"waiting_for": "Finance approval of the export columns, from anyone on the finance team."
},
"event": {
"source": "chat",
"from": "priya (finance)",
"content": "Looking at the export columns this afternoon."
}
}Unrelated message
Expected: ignore: nothing to do with the export.
{
"agent": {
"goal": "Ship the v2 billing export once finance approves the column list.",
"waiting_for": "Finance approval of the export columns, from anyone on the finance team."
},
"event": {
"source": "email",
"from": "it-helpdesk",
"content": "Reminder: laptops need the OS update by Friday."
}
}Borderline cases
One case near the line for each question. Use them to test your wording before you trust the thresholds.
wake_decision
A conditional approval: it approves most columns but asks for one change.
{
"agent": {
"goal": "Ship the v2 billing export once finance approves the column list.",
"waiting_for": "Finance approval of the export columns, from anyone on the finance team."
},
"event": {
"source": "chat",
"from": "priya (finance)",
"content": "Approved except the tax_region column, please rename it to region. Otherwise fine."
}
}Try it
Save an example state as state.json, then run the spec locally. Local mode makes no network call and needs no key; answers are synthetic unless a recorded fixture matches.
pnpm bandwise run --local bandwise/sets/wake-gate.json state.jsonBandwise is an independent product built on TypeSafe's System One models. It is not TypeSafe's documentation. For the System One models themselves, see docs.typesafe.ai.