Incident Management¶
What you'll learn: How incidents are created, the incident lifecycle, and how to triage and resolve them.
What is an incident?¶
An incident is a policy violation record. When the engine evaluates a step and one or more policies return warn or block, it reports the violation to the configured incident sink (by default, the same destination as the behavioral trace, see Configuring the incident sink).
Violations are grouped, not duplicated. Each violated policy produces an incident, but while an active or ignored incident already exists for the same agent, policy and environment (at either enforcement point, step_execution or agent_registration), a repeat violation updates it instead of creating another: last_occurrence moves forward, occurrence_count increases, and task_id and details show the latest occurrence. Once an incident is resolved, the next violation opens a new one. A step that breaks three policies still yields three incidents.
Incidents provide the audit trail: they record what was violated, when, by which agent, and in which task.
Incident lifecycle¶
active → resolved
→ ignored
| Status | Meaning |
|---|---|
| active | What the platform creates: a violation nobody has dealt with yet. |
| resolved | The violation has been addressed (code fixed, policy adjusted, or root cause mitigated). |
| ignored | Reviewed and determined to be a false positive or acceptable risk. |
A resolved or ignored incident can be reactivated. The API also accepts open and fixed as status filter values, but nothing in the platform sets either today: an incident is not moved to fixed when the agent later passes the policy.
Incident data¶
Each incident includes:
| Field | Description |
|---|---|
incident_id |
The incident's identifier (inc_...). |
agent_id |
The agent that triggered the violation. |
policy_id |
The policy that was violated (null when the reported policy no longer resolves; the incident keeps a policy_snapshot of its name, manifest, rule and severity). The title reads Policy violation: <policy name> (<manifest name>). |
severity |
The violated policy's severity. |
status |
active, resolved or ignored (see above). |
task_id |
The task in which the violation last occurred (for step violations). |
environment |
The agent's environment. |
details |
enforcement_point (step_execution or agent_registration), step_name, kind, action_id, action (warn or block), risk_score (0.0 to 1.0, for the whole step) and violation_details from the rule. |
created_at, last_occurrence, occurrence_count |
When the incident was created, when the violation last occurred, and how many violations were grouped into it. |
resolved_at, resolved_by, resolution_notes |
Set when the incident is resolved. |
Dashboard workflow¶
- Navigate to Incidents in the sidebar.
- Filter by status, severity, environment, or the agent's risk classification.
- Click a row to expand it: the table shows ID, title, severity, status, environment, agent, occurrence count and last occurrence, and the expanded row shows the full details.
- Change its status with the buttons at the foot of the expanded row. Each asks for confirmation first:
- Resolve (active incident): the violation has been dealt with. You are recorded in
resolved_by, and the next violation of the same policy by the agent opens a new incident. - Ignore (active incident): a false alarm or an accepted risk. Later violations are still counted on this incident, which stays ignored.
- Reactivate (resolved or ignored incident): back to
active.
Any workspace member who can see the incident can change its status; there is no role restriction. The same changes are available through the API endpoints below, with a member's JWT.
API endpoints¶
| Method | Path | Description |
|---|---|---|
POST |
/api/v1/incidents |
Report violations. Called by the engine with the agent's KvKey- API key; returns 201 with the created and updated counts. |
GET |
/api/v1/incidents |
List incidents. Filters: agent_id, policy_id, environment, status, severity; skip and limit (default 50, max 1000). |
GET |
/api/v1/incidents/{incident_id} |
Get incident details. {incident_id} is the inc_... identifier. |
PUT |
/api/v1/incidents/{incident_id}/resolve |
Resolve incident. Optional body resolution_notes. |
PUT |
/api/v1/incidents/{incident_id}/ignore |
Ignore incident. |
PUT |
/api/v1/incidents/{incident_id}/reactivate |
Reactivate a resolved or ignored incident (400 from any other status). |
Incidents are never deleted — they are part of the audit trail. They travel with their agent: moving an agent to another workspace carries its logs and incidents along, hash chain intact, and each moved incident carries a self-contained snapshot of the policy it violated, so deleting the workspace it left cannot destroy it.
Configuring the incident sink¶
Incidents follow the same location + format sink model as behavioral
traces. By default the incident sink inherits the trace sink
(KV_LOG_LOCATION / KV_LOG_FORMAT), substituting the …/api/v1/incidents
path for the Kyvvu kv format. So if traces already flow to the platform,
incidents do too — no extra configuration needed.
To route incidents to a different destination, set KV_INCIDENT_LOCATION
(and optionally KV_INCIDENT_FORMAT):
# Send incidents to the platform explicitly (kv format → …/api/v1/incidents)
export KV_INCIDENT_LOCATION=https://platform.kyvvu.com
export KV_INCIDENT_FORMAT=kv
KV_INCIDENT_LOCATION accepts the same values as KV_LOG_LOCATION — an HTTP
URL, a file path (JSONL), stdout, or none/empty to disable:
# Local debugging — print incident JSON to stdout
export KV_INCIDENT_LOCATION=stdout
# Emit a standalone kyvvu.incident OpenTelemetry span
export KV_INCIDENT_LOCATION=http://collector:4318
export KV_INCIDENT_FORMAT=otlp
Next steps¶
- Dashboard Guide — navigate the dashboard
- Reports — generate audit reports from incident data
- Policies and Rules — understand how violations are determined