Atomic Behaviours
What you'll learn: The 12 behaviour types that form Kyvvu's canonical vocabulary, how step_type + scope + verb classifies every agent action, and where properties fit in.
The vocabulary
Every action an agent takes is classified into one of 12 atomic behaviour types. Four describe the task lifecycle; eight describe the agent's actions within a task. Together with a scope (task or step) and an HTTP-style verb (GET, POST, PATCH, DELETE, or none), they form the vocabulary the engine operates on.
task.start
task
--
A task begins.
task.end
task
--
A task completes normally.
task.error
task
--
A task terminates with an error.
task.idle
task
--
The agent is idle within a task (heartbeat / keepalive).
step.resource
step
GET/POST/PATCH/DELETE
Read or mutate an external resource (DB, file, API).
step.message
step
GET/POST
Receive (GET) or send (POST) a message.
step.self
step
GET/POST/PATCH/DELETE
Read/write the agent's own internal state (memory, scratchpad, plan).
step.model
step
POST
Send a prompt to an LLM and receive a completion.
step.credential
step
GET
Retrieve a secret, token, or credential.
step.exec
step
--
Execute code (run a script, call a function, shell out).
step.gate
step
--
Cross a gate — human approval, policy check, guardrail.
step.unknown
step
--
Uncategorisable behaviour (template fallback).
These combinations are enforced by the Behavior model validator. Any (step_type, scope, verb) tuple outside the valid set raises on construction.
Two evaluation points
Behaviours are evaluated at two points:
Agent registration — once, before the first task begins. Policies with
scope: agent_registrationrun against the agent's metadata (purpose, tools, classification).Every step — before each step executes. Policies with
scope: step_executionrun against the intended Behavior and the task's history.
task.* behaviours (start, end, error, idle) evaluate against step_execution-scoped policies, exactly like step.* behaviours. There is no separate "task_execution" scope. Task lifecycle events are atomic steps that happen to sit at the boundaries of a task.
Properties
Everything beyond the (step_type, scope, verb) tuple lives in properties — a nested dict that policies can inspect. Properties distinguish a step.resource reading customer-data from one reading product-data. The type is the same; the property is different.
Standard property groups:
target
The thing being acted on
domain, table, object_id, system, trust
auth
Authentication scope
scope (read/write/admin), principal
data
Payload classification
classification (pii, public), fields
model
LLM details (for step.model)
provider, name, parameters
exec
Execution details (for step.exec)
runtime, isolation, side_effect_class
guard
Gate details (for step.gate)
gate_type (human_approval, policy_check)
message
Message details (for step.message)
channel, sender, recipient
usage
Usage metrics (for step.model outputs)
prompt_tokens, completion_tokens, cost_usd
Custom property groups are permitted. The engine passes them through unchanged, and rule functions read them via dot-path accessors (e.g. target.table, data.classification).
Worked example
A step.resource GET reading customer data:
A policy using the domain_allowlist rule could check target.domain. A policy using pii_in_request could scan the input for sensitive patterns. The history_contains rule could check whether this behaviour has already occurred in the task.
Mapping from frameworks
Templates bridge framework-specific events to the behavior vocabulary above. Each template is a YAML file with ordered rules that map event types (e.g. LangChain's on_llm_start, or a decorator's step_type) to (step_type, scope, verb) tuples with property extraction. See Templates for how this works, and the Template Authoring Guide for how to write your own.
Next steps
Policies and Rules — how policies use behaviour types and properties to make decisions
Templates — how the SDK maps framework events to this vocabulary
Built-in Rules Reference — all 26 rules and which behaviour types they operate on
Last updated
