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

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

***

## 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 26 rules and which behaviour types they operate on


---

# Agent Instructions: 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:

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

The question should be specific, self-contained, and written in natural language.
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.
