Ch11. Schedules, State, Hooks
Connect Eve cron schedules, durable state, and stream-event hooks to automation, memory, and audit.
핵심 요약
- Schedules, state, and hooks make an agent an operated system, not just a chat endpoint.
- Durable state is small per-session memory; it is not a database replacement.
- Hooks run after stream events and can fail the run, so audit code is production code.
Production agents do not only respond to users. They also run checks, remember session-scoped facts, and write audit trails.
Schedules
Schedules live under agent/schedules/ and are root-agent only.
Markdown Schedule
---
cron: "0 9 * * *"
---
Prepare the daily risk report for open incidents.Markdown schedules are fire-and-forget task-mode runs. They cannot wait for human input or OAuth sign-in. Use them for read-only or already-authorized work.
Handler Schedule
import { defineSchedule } from "eve/schedules";
export default defineSchedule({
cron: "*/15 * * * *",
async run({ receive, appAuth }) {
await receive({
message: "Check stale incidents and summarize any that need attention.",
auth: appAuth,
});
},
});Handler schedules can route work through a channel and carry app-level auth context.
Schedule Standards
| Concern | Standard |
|---|---|
| timezone | cron is UTC unless explicitly handled |
| idempotency | same schedule may be triggered again |
| auth | use appAuth for app-owned work |
| output | decide where results go |
| failure | alert and retry policy |
| eval | smoke schedule behavior |
Durable State
defineState gives per-session durable memory.
import { defineState } from "eve/context";
export default defineState({
default: () => ({ definitions: {} as Record<string, string> }),
});Use state for small, session-scoped facts such as:
- user's selected project
- current investigation id
- glossary entries gathered during a session
- workflow progress markers
Do not use state for:
- large documents
- tenant-wide memory
- OAuth token storage
- data requiring complex queries
State Use Criteria
| Need | Use |
|---|---|
| per-session small memory | defineState |
| large artifacts | sandbox files or object storage |
| tenant memory | database |
| credentials | connection/tool auth |
| audit trail | hooks/external log |
Hooks
Hooks subscribe to runtime stream events from agent/hooks/.
import { defineHook } from "eve/hooks";
export default defineHook({
events: {
"action.result": async (event, ctx) => {
await writeAuditLog({
sessionId: ctx.session.id,
action: event.name,
success: event.status === "success",
});
},
},
});Use hooks for:
- audit logs
- metrics
- alerting
- warehouse ingestion
- incident timelines
Hook Failure Is Real Failure
If a hook throws, the turn/session can fail. Make hook code reliable:
- isolate network calls behind retry/timeout
- avoid throwing for optional analytics
- use a dead-letter path for audit export failure
- do not put business side effects only in hooks
Hook vs Channel Event Handler
| Surface | Purpose |
|---|---|
| channel handler | deliver to external platform and update adapter state |
| hook | audit, metrics, synchronization |
| tool | privileged action requested by model |
| instrumentation | tracing and telemetry setup |
Tool Result Narrowing
Hook event payloads can include tool results. Apply the same data-minimization mindset as toModelOutput.
| Risk | Response |
|---|---|
| PII in audit log | redact or hash |
| raw provider output | store pointer instead |
| high-cardinality metrics | aggregate |
| secrets in error text | scrub |
Operating Patterns
| Pattern | Eve surface |
|---|---|
| daily report | schedule + channel delivery |
| approval audit | approval-gated tool + action.result hook |
| session memory | defineState |
| incident timeline | hooks + external store |
| stale session cleanup | schedule + external DB |
Checklist
| Item | Standard |
|---|---|
| schedules | UTC, idempotency, alerting |
| state | small and session-scoped |
| hooks | reliable, redacted, monitored |
| audit | external durable store |
| eval | schedule/state/hook regression coverage |