Behaviors

Behavior bundles — directives and toolsets for daemon-governed agents

Behaviors Guide

Behaviors are a new capability type in AIWG — the layer above skills. They come in two complementary forms that share the same core insight: hooks change the execution model.

Two Layers, One Concept

The AI tool ecosystem has a capability spectrum that is often conflated:

LayerInvocationExecutionHooksDeployed to
SkillNLP invocationLLM inferenceNoExternal platforms
Skill with scriptsNLP invocationLLM + scriptsNoExternal platforms
Deployable behaviorEvents + NLPScripts + hooksYesExternal platforms (OpenClaw, etc.)
Runtime behaviorAgent constructionDirectives injectedYes (continuous)Runtime only — daemon process

The key insight shared by both: hooks flip the dependency direction. A skill waits to be called. A behavior subscribes to the system and fires when conditions are met.

Deployable Behaviors (`BEHAVIOR.md`)

Defined as `BEHAVIOR.md` files with scripts and event hooks. Deployed to platforms like OpenClaw via `aiwg use --provider openclaw`. OpenClaw is the first platform to support them natively — on platforms without hook support they degrade to enhanced skills.

Use when: You need a capability that reacts to file changes, tool completions, schedules, or other system events — not just when a user asks.

Jump to Deployable Behaviors

Runtime Behaviors (YAML)

Defined as YAML files with directives and tools. Attached to daemons and agent loops at construction time. Never deployed to external platforms — they operate inside the AIWG runtime.

Use when: You need unconditional constraints on a long-running agent — budget limits, concurrency caps, process governance — that the LLM cannot choose to ignore.

Jump to Runtime Behaviors


Deployable Behaviors

Deployable behaviors are the missing artifact type in the AI tool ecosystem: reactive, event-driven capabilities with scripts, hooks, and structured inputs. They are deployed to platforms the same way skills, agents, and commands are.

Why They Exist

Skills are pull-based: a user invokes them, they run once, they return. OpenClaw introduced skills-with-scripts — procedurally more powerful, still pull-based. The missing piece is the reactive capability — one that subscribes to system events and fires when conditions are met.

A `security-sentinel` behavior doesn't need a user to type "run security scan" — it fires every time a `.ts` file is written, after every deploy, and on a 30-minute schedule. The user can still invoke it explicitly, but it also participates in the system continuously.

Directory Structure

agentic/code/behaviors/<name>/
├── BEHAVIOR.md       ← definition: triggers, hooks, inputs, scripts, manifest
└── scripts/
    ├── main.sh       ← explicit invocation entry point
    ├── on-write.sh   ← called by on_file_write hook
    └── post-deploy.sh ← called by on_tool_complete hook

BEHAVIOR.md Format

---
name: security-sentinel
version: 1.0.0
description: Reactive security scanning that monitors code changes, deployment events, and runs scheduled audits.
platforms: [openclaw, claude-code]

# NLP triggers — invocation path (same as skills)
triggers:
  - "run security scan"
  - "check for vulnerabilities"
  - "security audit"

# Typed, structured inputs
inputs:
  - name: target
    type: string
    required: false
    default: "."
    description: File or directory to scan
  - name: severity
    type: enum
    values: [low, medium, high, critical]
    default: medium
    description: Minimum severity level to report

# Event hooks — reactive path, what makes it a behavior
hooks:
  on_file_write:
    - filter: "**/*.{ts,js,py}"
      action: run_script
      script: scripts/on-write.sh
  on_tool_complete:
    - tool: deploy
      action: run_script
      script: scripts/post-deploy.sh
  on_schedule:
    - cron: "*/30 * * * *"
      action: run_script
      script: scripts/main.sh

# Executable scripts
scripts:
  main: scripts/main.sh
  on-write: scripts/on-write.sh
  post-deploy: scripts/post-deploy.sh

# Manifest — discovery, composition, dependency metadata
manifest:
  category: security
  requires:
    bins: [npm, node]
    env: []
  outputs:
    - type: report
      path: .aiwg/reports/security/
  composable_with: [code-review, test-runner]
---

# Security Sentinel

Monitors source code changes and deployment events for security issues. On explicit invocation,
runs a full audit. When subscribed via hooks, provides continuous lightweight scanning.

## What It Scans

- Hardcoded secrets and API keys
- Dependency vulnerabilities (npm audit)
- OWASP top 10 patterns in changed files

## Outputs

Reports written to `.aiwg/reports/security/` in structured JSON.

Hook Events

Behaviors subscribe to events in the platform's event system. AIWG defines standard hook names that platforms implement.

File System

HookFires whenFilter support
`on_file_write`Any file is writtenGlob pattern (`"**/*.ts"`)
`on_file_delete`Any file is deletedGlob pattern
`on_file_rename`A file is renamed or movedGlob pattern

Tool Lifecycle

HookFires whenFilter support
`on_tool_complete`An AI tool call completesTool name
`on_tool_error`An AI tool call failsTool name
`on_session_start`Agent session begins
`on_session_end`Agent session ends

Version Control

HookFires whenFilter support
`on_commit`A git commit is madeBranch pattern
`on_pr_open`A pull request is opened
`on_push`Code is pushed to remoteBranch pattern

Schedule

HookFires whenFormat
`on_schedule`Cron schedule triggersStandard cron expression

Structured Inputs

Unlike skills (conversational input), behaviors declare typed schemas. Platforms use these to render input forms or validate CLI arguments.

Supported types: `string`, `number`, `boolean`, `enum`, `array`, `object`

When invoked via NLP, AIWG extracts inputs from the conversation. When triggered via hooks, inputs are passed as environment variables to the script.

Writing Scripts

Scripts are bash and receive context via environment variables:

#!/usr/bin/env bash
set -euo pipefail

# Input values (from inputs: schema)
TARGET="${BEHAVIOR_INPUT_TARGET:-.}"
SEVERITY="${BEHAVIOR_INPUT_SEVERITY:-medium}"

# Hook context (set when triggered by a hook, empty on explicit invocation)
HOOK_EVENT="${BEHAVIOR_HOOK_EVENT:-}"
HOOK_PATH="${BEHAVIOR_HOOK_PATH:-}"      # on_file_write: path that changed
HOOK_TOOL="${BEHAVIOR_HOOK_TOOL:-}"      # on_tool_complete: tool that completed

# Project context
REPORT_DIR="${AIWG_REPORTS_DIR:-$(pwd)/.aiwg/reports}/security"
mkdir -p "$REPORT_DIR"

echo "[security-sentinel] Scanning $TARGET (triggered by: ${HOOK_EVENT:-manual})"

Portability rules:

  • Use `#!/usr/bin/env bash` (not `/bin/bash`)
  • Avoid GNU-specific flags (macOS uses BSD tools)
  • Declare binary dependencies in `manifest.requires.bins`

Graceful Degradation

On platforms without hook support, behaviors degrade to enhanced skills — only the `triggers:` path activates, `hooks:` is ignored.

PlatformScriptsHooksStatus
OpenClawYesYesFull support — first implementation
Claude CodeNoPlannedDegrades to skill
CursorNoPlannedDegrades to skill
WarpNoPlannedDegrades to skill

Deploying to OpenClaw

# Deploy SDLC framework (includes behaviors)
aiwg use sdlc --provider openclaw

# Deploy all frameworks
aiwg use all --provider openclaw

# Verify
openclaw behaviors list

Behaviors land in `~/.openclaw/behaviors/<name>/`. OpenClaw discovers them automatically and wires hooks at startup.

Scaffolding a Behavior

# Scaffold with defaults
aiwg add-behavior my-behavior

# With hooks pre-configured
aiwg add-behavior test-watcher --hooks on_file_write,on_schedule --category testing

# Interactive
aiwg add-behavior --interactive

Included Behaviors

BehaviorCategoryHooksDescription
`security-sentinel`securityon_file_write, on_deploy, on_scheduleContinuous security scanning
`test-watcher`testingon_file_write, on_scheduleReactive test execution
`build-monitor`cion_tool_complete, on_scheduleBuild health tracking
`quality-gate-watcher`sdlcon_commit, on_pr_openSDLC gate enforcement
`artifact-sync`sdlcon_file_write (.aiwg/**)Artifact index sync

Runtime Behaviors

Runtime behaviors are a separate but related concept: named, versioned capability bundles that attach to long-running agents (daemons, agent loops) at initialization and remain active for the agent's entire lifetime.

What Are Runtime Behaviors

A runtime behavior is a YAML file that packages two things together:

  • Directives — rules the agent must follow unconditionally, regardless of LLM reasoning
  • Tools — callable functions exposed to the agent at runtime

The key distinction from other AIWG primitives:

PrimitiveInvocationLifecycleDeployment
ToolLLM decides whether to callPer-callExternal platforms
HookFires on discrete events (start, stop, write)Event-drivenExternal platforms
RuleLoaded into context at session startPer-sessionExternal platforms
Runtime behaviorAttached at agent construction, always activeFull agent lifetimeRuntime only — never deployed to external providers

Runtime behaviors exist because some capabilities cannot be optional. A budget limiter the LLM can choose to ignore is not a budget limiter. A process-group kill that only fires when the model decides to invoke it is unreliable. Runtime behaviors enforce capabilities at the runtime layer, below the LLM reasoning layer.

This design follows the AutoGen `register_reply()` pattern: capabilities registered at construction time execute on every message cycle regardless of what the model chooses.

See `.aiwg/architecture/adr-behaviors-sticky-capabilities.md` for the full architecture decision.

Schema reference

name: my-behavior
version: "1.0.0"
description: >
  What this behavior does and which agent types it applies to.

# Agent types this behavior is designed for.
# The runtime will warn (but not block) if attached to an unlisted type.
agentTypes:
  - daemon
  - agent-loop
  - long-running-agent

directives:
  - id: unique-directive-id          # Stable identifier — used for merge and override
    rule: >
      The rule text that the agent must follow. Write this as an imperative
      instruction. It is injected into the agent's system prompt and treated
      as a hard constraint.
    defaults:                         # Optional: default parameter values the directive uses
      param: value

tools:
  - tool: tool-name                   # Unique tool identifier within this behavior
    description: >
      What this tool does. Shown to the agent alongside its schema.
    schema:
      type: object
      properties:
        paramName:
          type: string
          description: What this parameter controls
      required: []

Field reference

FieldRequiredDescription
`name`yesUnique behavior name. Used in `behaviors` config key and CLI commands.
`version`yesSemantic version string.
`description`yesHuman-readable summary.
`agentTypes`yesList of agent types this behavior targets.
`directives`noArray of directive objects. May be empty.
`directives[].id`yesStable identifier. Must be unique within the behavior. Used for merge conflict resolution.
`directives[].rule`yesImperative rule text injected into the agent's system prompt.
`directives[].defaults`noDefault parameter values referenced by the rule.
`tools`noArray of tool definitions. May be empty.
`tools[].tool`yesTool name. Must be unique within the behavior.
`tools[].description`yesDescription shown to the agent.
`tools[].schema`yesJSON Schema object describing the tool's input.

Discovery tiers

The runtime discovers behaviors from three locations, in precedence order:

TierPathPurpose
Framework`agentic/code/behaviors/`Shipped defaults — maintained by AIWG
Project`.aiwg/behaviors/`Project-specific overrides and additions
User`~/.config/aiwg/behaviors/`User preferences applied across all projects

When the same behavior `name` appears in multiple tiers, the more specific scope wins:

project > framework > user

This means a project-level `ops-toolset.yaml` fully replaces the framework-level one for that project. The user tier has the lowest precedence because it applies broadly; project-level intent should override broad preferences.

Precedence example

Given:

  • `agentic/code/behaviors/ops-toolset.yaml` (framework, version 1.0.0)
  • `.aiwg/behaviors/ops-toolset.yaml` (project, version 1.1.0 with a modified `budget-gate` directive)

The runtime loads the project version. The framework version is ignored for this project.

Built-in behaviors

ops-toolset

Path: `agentic/code/behaviors/ops-toolset.yaml` Version: 1.0.0 Agent types: `daemon`, `agent-loop`, `long-running-agent`

The default behavior for operational agents. It is included automatically when a daemon is configured with `"behaviors": ["ops-toolset"]`.

Directives (5):

Directive IDSummary
`process-group-kill`Use `process.kill(-pid, signal)` to terminate entire process trees. Prevents orphaned child processes.
`restart-intensity`Track restart count per task within a sliding window. Mark permanently failed when threshold is exceeded (Erlang/OTP pattern).
`concurrency-cap`Never exceed `max_concurrent` simultaneous sessions. Queue overflow is rejected with a structured error.
`budget-gate`Check aggregate spend before spawning. Warn at 90% of daily limit; block at 100%.
`zombie-reap`Periodically reconcile PID files against running processes. Remove stale entries.

Tools (7):

ToolDescription
`process-list`List running agent loops with PID, status, start time, and resource usage
`process-kill`Kill a loop by ID using process group kill
`resource-snapshot`Current CPU, memory, load average, queue depth, and daemon uptime
`circuit-status`Circuit breaker state: `closed`, `open`, or `half-open`, with failure count and cooldown remaining
`queue-inspect`Queue depth, max depth, oldest entry, and priority distribution
`loop-history`Completed loop summaries: ID, duration, exit status, iteration count, cost
`budget-remaining`Daily limit, spent, remaining, and percent used

The tools in `ops-toolset` map directly to the `daemon.*` IPC methods documented in the Daemon Guide. When the agent invokes `resource-snapshot`, it calls the same underlying `MetricsCollector` that `daemon.resource.snapshot` uses.

Creating custom behaviors

Step 1: Choose the right tier

  • Reusable across all your projects → `~/.config/aiwg/behaviors/`
  • Specific to this project → `.aiwg/behaviors/`
  • Contribution to AIWG itself → `agentic/code/behaviors/`

Step 2: Create the YAML file

Name the file `<behavior-name>.yaml`. The `name` field inside must match the filename without extension.

Example: a cost-reporting behavior for finance-sensitive projects

name: cost-reporter
version: "1.0.0"
description: >
  Emits structured cost reports after each loop completion.
  Designed for projects with chargeback or billing tracking requirements.

agentTypes:
  - daemon
  - agent-loop

directives:
  - id: emit-cost-on-complete
    rule: >
      After every loop completes, emit a structured cost record including
      loop ID, model, input tokens, output tokens, and total USD cost.
      Write the record to .aiwg/reports/cost-log.jsonl in append mode.
    defaults:
      output_path: ".aiwg/reports/cost-log.jsonl"

  - id: cost-ceiling
    rule: >
      If a single loop exceeds per_loop_limit_usd, abort it gracefully
      and record the ceiling event in the cost log with reason "per-loop-ceiling".
    defaults:
      per_loop_limit_usd: 5.00

tools:
  - tool: cost-log-tail
    description: >
      Return the last N entries from the cost log file.
    schema:
      type: object
      properties:
        limit:
          type: integer
          default: 10
          description: Number of entries to return
      required: []

Step 3: Verify discovery

aiwg behavior list

The output should include `cost-reporter` with its tier (project or user).

Step 4: Attach to a daemon

In `.aiwg/daemon.json`:

{
  "supervisor": {
    "behaviors": ["ops-toolset", "cost-reporter"]
  }
}

Restart the daemon to apply:

aiwg daemon stop && aiwg daemon start

Step 5: Confirm attachment

aiwg behavior info cost-reporter

Output shows version, tier, directives, and whether it is currently attached.

CLI commands

# List all discovered behaviors across all tiers
aiwg behavior list

# Show full detail for a specific behavior
aiwg behavior info <name>

# Attach a behavior to the running daemon (hot-attach, no restart)
aiwg behavior apply <name>

# Detach a behavior from the running daemon
aiwg behavior remove <name>

behavior list output

NAME              VERSION  TIER       AGENT TYPES                  DIRECTIVES  TOOLS
ops-toolset       1.0.0    framework  daemon, agent-loop, ...      5           7
cost-reporter     1.0.0    project    daemon, agent-loop           2           1

The `TIER` column shows where the behavior was loaded from. When a name is overridden by a higher-precedence tier, the lower-tier entry is not shown.

Merge rules

When multiple behaviors are attached to the same agent, their directives and tools are merged into a single capability set.

Directives

Directives are unioned by `id`. If two behaviors define a directive with the same `id`, the later one in the attachment order wins, and a warning is emitted:

WARN: directive id "budget-gate" defined in both "ops-toolset" and "cost-reporter".
      "cost-reporter" wins (later in attachment order). To suppress, set explicit priority.

To suppress the warning and declare intent explicitly, add a `priority` field:

directives:
  - id: budget-gate
    priority: 10          # Higher number wins. Default is 0.
    rule: >
      ...

Tools

Tools are unioned by `tool` name. A name collision between behaviors is a hard error (not a warning) because tool schemas must be unambiguous:

ERROR: tool name "process-kill" is defined in both "ops-toolset" and "my-behavior".
       Rename one of them or remove the duplicate.

Safe combinations

Behaviors are designed to combine safely when they target different concerns. The built-in `ops-toolset` defines governance directives; project behaviors typically add domain-specific reporting or policy. Collision only occurs when two behaviors try to own the same directive or tool name.

Troubleshooting

Behavior not discovered

aiwg behavior list

If the behavior is missing, verify the file is in one of the three discovery paths and that the `name` field in the YAML matches the filename (without `.yaml`).

Directive conflict warning on startup

Two attached behaviors define the same directive `id`. The later behavior in the `behaviors` array wins. If the outcome is wrong, either rename the directive in your custom behavior or set `priority` fields explicitly.

Tool name collision error

Two attached behaviors define the same `tool` name. Rename the tool in your custom behavior — built-in tool names should not be shadowed because the daemon's IPC layer depends on them.

Behavior attached but not taking effect

Directives are injected into the agent's system prompt at construction time. If the agent was already running when `aiwg behavior apply` was called, the directive applies to new sessions spawned after the attach. Existing running sessions are unaffected until they complete and are restarted.

Behaviors vs Skills vs Agents

SkillDeployable BehaviorRuntime BehaviorAgent
What it isNLP instructionsReactive platform artifactAgent capability bundleAI persona
TriggerUser invocationEvents + user invocationAgent constructionUser invocation
ScriptsNoYesNoNo (uses AI tools)
HooksNoYesYes (continuous)No
InputsConversationalTyped, structuredConfigConversational
LifetimeSingle invocationPersistent / subscribedFull agent lifetimeSingle session
Deployed toExternal platformsExternal platformsRuntime onlyExternal platforms
Use whenQuick NLP taskReact to system eventsUnconditional agent constraintsSpecialized AI role

Cross-References

  • OpenClaw Integration Guide — Deploying behaviors to OpenClaw
  • Daemon Guide — Daemon configuration, headend architecture, and IPC methods
  • CLI Reference — `aiwg add-behavior`, `aiwg behavior list/info/apply`
  • `agentic/code/behaviors/` — Behavior source files
  • `.aiwg/architecture/adr-behaviors-deployable-artifact.md` — Architecture decision for deployable behaviors
  • `.aiwg/architecture/adr-behaviors-sticky-capabilities.md` — Architecture decision for runtime behaviors
  • `.aiwg/architecture/adr-daemon-as-headend.md` — DaemonSupervisor headend architecture
  • Issue #540 — BEHAVIOR.md format spec
  • Issue #541 — Framework behavior source directories
  • Issue #542 — OpenClaw provider deployment
  • Issue #543 — `aiwg add-behavior` scaffolding command