Advanced 16 - Self-correction loop with built-in diagnostics
The lsp module ships five built-in validators that need no
external binary installed on the host: JSON, YAML, HTML, XML, and
Mermaid. Everything else - Python, Go, TypeScript, Rust, LaTeX, and
the rest - needs a real language server binary present on the
machine (pyright, gopls, texlab, ...); the module starts it
and speaks LSP to it, but doesn't bundle it.
Wire the lsp_diagnose hook to turn either into a self-correction
loop: after every file write, the agent gets the diagnostics back
in the tool result and can read them before its next move.
Built-in validators (no install needed)
| Extensions | Catches |
|---|---|
.json, .jsonc, .excalidraw | JSON syntax errors, with line + column |
.yaml, .yml | YAML syntax errors - and if the file is part of an app bundle (the manifest itself, or any file under a fragments//behavior/-style bundle folder), the real Digitorn compiler runs instead of a plain syntax check, so a bad include: or a schema error surfaces the same diagnostic digitorn install would give |
.html, .htm | Malformed HTML tokens |
.xml, .xsd, .xsl, .svg | XML syntax errors |
.mmd, .mermaid | Mermaid-specific issues: missing diagram header, unbalanced subgraph/end, reserved words used as node ids |
These five need nothing beyond the daemon itself. Everything else -
including TOML, which has no validator at all, built-in or
otherwise - needs a real external language server wired under
tools.modules.lsp.config.servers, covered in
LSP.
The YAML
app:
app_id: json-selfcorrect
name: JSON Self-Correction Loop
version: "1.0"
runtime:
mode: conversation
workdir_mode: auto
max_turns: 6
timeout: 180
agents:
- id: main
role: assistant
brain:
provider: openai
backend: openai_compat
model: gpt-5-mini
config:
api_key: placeholder
base_url: https://api.openai.com/v1
temperature: 0.2
max_tokens: 4096
system_prompt: |
You author JSON config files inside the workspace.
Use Write to create files, Edit to fix them. After each
write, call lsp.notify_change on the same path to get
diagnostics.
Workflow:
1. Write the file.
2. Call lsp.notify_change(path=<the file>).
3. If any diagnostic has severity "error", Edit to fix the
most pressing one and repeat from step 2.
4. Once diagnostics are empty, reply with one short
confirmation line.
tools:
modules:
filesystem: {}
lsp: {}
capabilities:
default_policy: auto
grant:
- module: filesystem
tools: [read, write, edit]
- module: lsp
Sample flow
Turn 1: write a broken file, then check it.
Write(path="config.json", content="{\"name\": \"demo\",}")
lsp.notify_change(path="config.json")
→ {
"diagnostics": [
{
"line": 1,
"column": 19,
"severity": "error",
"message": "invalid character '}' looking for beginning of object key string"
}
]
}
Turn 2: fix it.
Edit(path="config.json", old_string="\"demo\",}", new_string="\"demo\"}")
lsp.notify_change(path="config.json")
→ { "diagnostics": [] }
Wiring it as an automatic hook
Rather than teaching the agent to call lsp.notify_change itself,
wire lsp_diagnose to fire automatically after every write and
inject the diagnostics straight into the write's own tool result:
runtime:
hooks:
- id: lint_after_write
"on": tool_end
condition:
type: tool_name
match: [filesystem.write, filesystem.edit]
action:
type: lsp_diagnose
inject_result: true
cooldown: 0.5
inject_result: true appends the diagnostics text to the write's
own result instead of pushing a separate message, so the agent
sees "wrote the file, here's what's wrong with it" in one place.
The hook resolves which file changed on its own - it checks
path, file_path, filename, file, and tool.result.path on
the triggering call, in that order, so it works across
filesystem, mcp servers, and custom writers without extra
configuration in the common case.
When to reach for this
- Any workflow where the agent generates structured files (configs, JSON payloads, app bundles).
- Editing a Digitorn app bundle itself - the YAML validator's
compiler-backed path means a broken
include:or a bad field surfaces the same compiler diagnosticdigitorn installwould give, automatically, after every edit. - A safe floor under real language-server wiring: even before you
install
pyrightorgoplson the host, JSON/YAML/HTML/XML/ Mermaid files already get real syntax checking.
For type-level diagnostics, style rules, or anything beyond what
the five built-ins cover, install and configure a real LSP server
in the lsp: module - see LSP.