Skip to main content
Two mechanisms let you observe and constrain a Karta app without touching the harness: hooks (react to lifecycle events) and policies (validate messages before they run).

Hooks

Register a handler for a lifecycle event with @app.on(...). Handlers receive a HookEvent carrying the session, message, and any event-specific payload.

Available events

Use hooks for logging, metrics, side effects (notify a channel on handoff), or enrichment - they observe the flow without owning it. Hook handlers are best-effort. Handlers fired by synchronous state changes, such as session.created and agent.handoff, may run after a later event. Exceptions are logged and do not fail the turn.

Policies

Policies validate messages against configurable rules before a turn runs - message counts and keyword gates.
A message that violates a policy is rejected before reaching the harness, so policy checks are cheap and deterministic - exactly the kind of guardrail you want in code rather than left to the model. max_tokens_per_session is accepted as a compatibility alias for max_messages_per_session; new code should use max_messages_per_session.
Hooks and policies run as part of Karta’s orchestration, around the harness. They do not see or alter conversation history (the harness owns that); they gate and observe the turns that flow through Karta. See How Karta works.