Templates
Note: This page covers behavior templates — YAML rules that map framework events to Kyvvu Behaviors. For policy manifests (compliance policy sets assigned to agents), see Manifests.
What you'll learn: How YAML templates map framework events to Behaviors, how matching works, and how to customize templates.
What templates do
Templates are the translation layer between your framework's events and Kyvvu's canonical vocabulary. When your agent calls an LLM, reads a database, or sends a message, the SDK needs to know which (step_type, scope, verb) tuple to use, and which properties to set. Templates define this mapping.
Without templates, every integration would need hardcoded mappings. With templates, the same SDK can support any framework — you just write a YAML file.
Built-in templates
The SDK ships with two built-in templates:
from kyvvu.templates import BehaviorTemplate
decorator_template = BehaviorTemplate.from_builtin("decorator")
langchain_template = BehaviorTemplate.from_builtin("langchain")decorator— for the@kv.stepdecorator integration. Maps decorator arguments directly to Behavior fields.langchain— for the LangChain/LangGraph callback handler. Maps LangChain callback events (on_llm_start,on_tool_start, etc.) to Behaviors.
How matching works
Templates use first-match-wins rule evaluation. Each template contains an ordered list of rules. For each framework event, the SDK walks the rules top to bottom and uses the first match.
Each rule has:
Conditions — predicates on the framework event (event type, function name, arguments).
Output — the Behavior fields to set (
step_type,scope,verb,properties).
If no rule matches, the template falls back to step.unknown.
Deep-merge semantics
When the SDK constructs a Behavior, it deep-merges three sources (in order of priority):
Caller overrides — values passed explicitly via
@kv.step(properties={...})orkv.start_task(properties={...}).Template output — the matched rule's output.
Framework defaults — base values from the framework event itself.
Caller overrides win at leaves. If the template sets properties.model.provider = "openai" and the caller sets properties.model.name = "gpt-4o", the result is {model: {provider: "openai", name: "gpt-4o"}}. But if the caller sets properties.model.provider = "anthropic", the caller's value wins.
Two tiers of developer effort
Templates support two levels of detail:
Lazy (generic fallback)
Use the built-in templates without customization. Every step gets a correct step_type and verb based on the framework event. Properties are sparse — mostly framework-inferred defaults.
This is fine for getting started and for development-time tracing.
Rich (named rules with properties)
Write a custom template with rules that match specific functions and set detailed properties — target system, data classification, auth scope, domain. This enables fine-grained policies that check properties like target.table == "customer-data" or target.trust == "external".
This is what production deployments use.
Loading custom templates
Three ways to use a custom template:
Template YAML structure
A minimal template:
Rules are evaluated in order. The fallback rule with empty conditions matches everything and should be last.
Next steps
Python Decorator — how
@kv.stepuses templatesLangChain / LangGraph — the LangChain callback handler and its template
Writing a New Integration — how to author templates for other frameworks
Further reading
Template Authoring Guide — step-by-step walkthrough for creating a custom behavioral template, including match semantics, property extraction, and a worked example.
Agent Pattern Templates — reference snippets for common agent architectures (RAG, ReAct, human-in-the-loop, multi-agent) that show how to map these patterns to Kyvvu's behavior vocabulary.
Last updated
