> For the complete documentation index, see [llms.txt](https://docs.kyvvu.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kyvvu.com/core-concepts/behaviours.md).

# 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.

| Step type         | Scope  | Valid verbs           | What it represents                                                    |
| ----------------- | ------ | --------------------- | --------------------------------------------------------------------- |
| `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.

> **"Scope" means two different things.** The `scope` in the table above is the **behaviour scope** (`task` or `step`) — the granularity of a single atom. It is derived automatically from the `step_type` prefix (`task.*` → `task`, else `step`), so you never set it in a [behavioural template](/core-concepts/templates.md). The `scope:` you write in a **policy/manifest** is the **policy scope** (`agent_registration` or `step_execution`) — it controls *when* a policy is evaluated (see below), not the granularity of a behaviour. Same word, unrelated axes.

## Two evaluation points

Behaviours are evaluated at two points:

1. **Agent registration** — once, before the first task begins. Policies with `scope: agent_registration` run against the agent's metadata (purpose, tools, classification).
2. **Every step** — before each step executes. Policies with `scope: step_execution` run 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:

| Group     | Purpose                                  | Example keys                                      |
| --------- | ---------------------------------------- | ------------------------------------------------- |
| `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:

```python
from kyvvu_engine.schemas import Behavior, Scope, StepType, Verb

Behavior(
    agent_id="agent-123",
    task_id="task-abc",
    scope=Scope.step,
    step_type=StepType.step_resource,
    verb=Verb.GET,
    step_name="read_customer_record",
    input={"customer_id": "CUST-9981"},
    properties={
        "target": {
            "system": "salesforce",
            "table": "customer-data",
            "domain": "internal.crm.acme.com",
        },
        "auth": {"scope": "read", "principal": "agent-123"},
        "data": {"classification": "pii", "fields": ["name", "email", "phone"]},
    },
)
```

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](/core-concepts/templates.md) for how this works, and the [Template Authoring Guide](/integrations/authoring.md) for how to write your own.

***

## Next steps

* [Policies and Rules](/core-concepts/policies.md) — how policies use behaviour types and properties to make decisions
* [Templates](/core-concepts/templates.md) — how the SDK maps framework events to this vocabulary
* [Built-in Rules Reference](/policy-authoring/rules-reference.md) — all 27 rules and which behaviour types they operate on


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kyvvu.com/core-concepts/behaviours.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
