Skip to content

Skill output contract

The service reads the skill's text output (rca.py, parse_output). The skill must follow this exactly.

Early exits

A single line at the very start of the output, nothing else:

RCA_OUTCOME: not_applicable - <short reason, e.g. "resolved/OK notification">
RCA_OUTCOME: insufficient_context - <what is missing>

Full report and chat message

The full report (layout in skills/rca/templates/report.md) is stored in the database. After it comes the chat message, the one message NIMI posts (layout and writing rules in skills/rca/templates/chat.md), between two marker lines:

RCA_CHAT
**<short title>**
`<subjects>` | <context>

**TL;DR:** …
**Cause** (likely, to be confirmed) …
**Steps to verify** …
**Now** …
**Do NOT** …
**Permanent fixes** …
**Also** …
**Related** …
END_RCA_CHAT

It uses simple Markdown (**bold**, _italic_, `code`, code blocks, - bullets); the provider converts it to its own markup. Sections that don't apply are left out. If the block is missing, the post falls back to the report's title and Summary.

Citations

The skill never writes URLs. To point at a stored message (e.g. the error log behind an alert) it writes [label](msg:<message_id>) with the message_id from skill_messages; for an earlier RCA, [label](rca:<result_id>); for code, [label](code:<project key>@<commit>/<path in repo>#L<line>). Before posting, the service checks each one: cited bot messages become links to the original message, cited RCAs link to their post (in the same destination when there is one), and cited code links to the file at that commit on the project's code host, and anything else — unknown IDs or projects, human messages, unsafe paths, Markdown links to URLs — is reduced to its label. Absolute local paths of registered checkouts are rewritten to <project>: <path in repo>. The stored report keeps the citations, so it records which messages each RCA relied on.

The output then ends with this block, as plain lines, one value per line, nothing after it:

RCA_FIELDS
origin: internal | upstream | undetermined
confidence: high | medium | low
self_healing: yes | no | unknown
repo: <project name in the registry, e.g. shop> | none
commit: <short sha analyzed> | none
sensitive_data: none | <where:type, where:type, …>
Field Values
origin internal (our code, config, infra, deploy), upstream (source system, third-party API/SDK, data), undetermined.
confidence high (direct evidence), medium (strong correlation), low (best hypothesis).
self_healing Whether a higher level re-runs the failed work automatically.
sensitive_data Types and locations only, never values. where: input, code, config, logs, docs, history. type: e.g. password, api-key, token, webhook-url, private-key, connection-string, email, phone, national-id, customer-data.

A report without the RCA_FIELDS block is treated as incomplete (an error), because it usually means the run was cut short. Invalid values are ignored. Each sensitive_data item raises a red flag.

Input context block

The service may prefix the input with a context block; it is the only instruction in the input:

RCA context (from the RCA service):
- Analyze only these subjects: <subject>, <subject>
- Already analyzed, do not re-analyze: <subject> (earlier RCA #<id>)
- History SQL: <path>/nimi-sql "<one SQL statement>"
---
<the alert / log text>