Data model
Executions, actions, events, and how they relate. Read this before writing non-trivial instrumentation.
Five concepts make up every integration. Understanding them individually — and how they relate — is the difference between a Klent integration that gives you audit-grade traces and one that gives you noise.
Agent
An opaque identifier you choose. Examples: support-agent, billing-agent-v2,
<internal feature name>-<version>. Klent does not track agents as first-class rows; the
identifier is simply recorded on each execution so you can filter on it.
Treat agent_id as stable. Rename it only when the agent's intent or tool surface
changes materially — the same way you would bump a major version of an API.
Execution
A session of agent activity. One execution per user request, per cron fire, per webhook invocation, per background job — whatever the smallest unit of "the agent did something end-to-end" is for your product.
An execution has:
id— the correlation key you thread through your code.agent_id— which agent ran.status—running,completed,failed, orcancelled.started_at/ended_at— wall-clock bounds.metadata— arbitrary JSON (user ID, tenant, feature flag, trace ID).
You are responsible for creating executions. Klent does not infer them.
Action
A proposed tool or API call. Actions are not stored as rows — they are the subject
of evaluateAction. The evaluation of an action produces a decision event.
Every action has:
- A tool name — the key the LLM picked (
send_email,transfer_funds, …). - An input payload — the arguments the LLM generated.
Evaluate every action before executing it. Evaluate actions even in systems where you do not yet have policies — the decision events give you the "intent" signal in your observability timeline for free.
Event
An append-only record on an execution's timeline. Events are immutable once written. The current event types:
| Type | Who writes it | Meaning |
|---|---|---|
decision | You or Klent | The agent (or the policy engine) reached a conclusion (allow / modify). |
action_requested | You | The LLM asked to call a tool. |
action_executed | You | A tool call finished successfully. |
action_blocked | Klent | A policy denied an action in evaluateAction. |
action_steered | Klent | A steer policy redirected an action to a different tool. |
pending_approval | Klent | An approve policy parked the action awaiting a human reviewer. |
approval_vote | Klent | One reviewer cast a vote on a pending action. Meaningful when required_approvals > 1. |
approval_resolved | Klent | A pending action reached its terminal state (approved or rejected). |
error | You | A tool call threw or a step failed. |
Klent writes the policy-engine events automatically. Everything else (action_requested,
action_executed, error) is yours to log via logEvent. The runTool /
runAnthropicAgent / runOpenAIAgent helpers in Auto-instrumentation
emit them for you.
Policy
A rule evaluated against an action. A policy has one or more conditions (AND-ed) and one of five effects:
allow— let the action through (useful for short-circuiting later denies).deny— block the action.modify— let it through with field substitutions applied to the input.approve— park the action until a human resolves it from the dashboard (HITL).steer— redirect the action to a different tool entirely.
Policies are stored per project, can be enabled: false to inert them without deletion,
and run in either enforce or shadow (dry-run) mode. They evaluate in creation order
and the first match wins.
See Policy engine for the full semantics.
Relationships
project ─┬─ many executions ─── many events
├─ many policies
├─ many pending_actions (rows produced by `approve` policies)
├─ many alert_rules ─── many webhook_deliveries
├─ many api_keys
└─ many members (users with a role)Every row in every table carries a project_id. Multi-tenancy is enforced at the SQL
level — the API middleware attaches the project ID from the caller's API key to the
context, and every query filters by it.
What not to log
- LLM prompts and completions. They can be large and contain user PII. Log the
shape of the interaction (tool, input keys, decision) and, if you need the full
conversation, store it elsewhere keyed by
execution.id. - Tool output bodies. Same reasoning. Store an ID or a hash.
- Anything you would not put in an audit log. Events are immutable and exportable; treat them with the same discretion as a finance ledger.