5. Putting It Together
The complete self-healing pipeline — monitor, diagnose, fix.
Let's connect everything into a single pipeline and organize the code into modules.
The complete agent
Here's the full main.qosm:
let check_health _ =
match service_get {url: "https://api.example.com/health", headers: []} with (
| Ok{value: body} ->
parse_json @{status: String, uptime: Int, errors: Array<String>} body
| Err{value: e} -> Err{value: e});
let get_errors _ =
match check_health ∅ with (
| Ok{value: health} ->
match .errors health with (
| [] -> Ok{value: "No errors"}
| errs -> Ok{value: foldl (λ acc e -> acc ++ "\n" ++ e) "Errors found:" errs})
| Err{value: e} -> Err{value: e});
let diagnose error_report =
diagnose_model @{severity: String, root_cause: String, suggested_fix: String}
`You are a site reliability engineer. Analyze this error report and provide a diagnosis.
Error report:
{{ error_report }}
Respond with severity (critical/warning/info), root_cause, and suggested_fix.`;
let create_issue diagnosis =
github_post {
url: "https://api.github.com/repos/myorg/myapp/issues",
body: to_json {
title: "[Auto] " ++ .severity diagnosis ++ ": " ++ .root_cause diagnosis,
body: .suggested_fix diagnosis,
labels: ["auto-healer"]
}
};
let heal _ =
match get_errors ∅ with (
| Ok{value: report} ->
match report with (
| "No errors" -> Ok{value: "All clear — no issues found"}
| errors ->
match diagnose errors with (
| Ok{value: d} ->
match .severity d with (
| "critical" -> create_issue d |> map_result (λ _ -> "Issue created: " ++ .root_cause d)
| "warning" -> create_issue d |> map_result (λ _ -> "Issue created: " ++ .root_cause d)
| _ -> Ok{value: "Low severity — no action: " ++ .root_cause d})
| Err{value: e} -> Err{value: e}))
| Err{value: e} -> Err{value: e});
The heal function is the entry point. It chains the entire pipeline: monitor → diagnose → conditionally fix.
The type tells the whole story
Check the inferred type of heal:
heal : Unit -> Result<String, QosmError> ! {Http.Get, LLM.Call, Http.Post}
Three effects, matching exactly the three capabilities we configured. Anyone reading this type knows the complete scope of what this agent does. No surprises, no hidden calls.
Using modules
As your agent grows, split it into modules. Click + in the file tabs to create helpers.qosm:
// helpers.qosm
let format_diagnosis d =
"[" ++ .severity d ++ "] " ++ .root_cause d ++ "\nFix: " ++ .suggested_fix d;
let is_actionable d =
match .severity d with (
| "critical" -> true
| "warning" -> true
| _ -> false);
Then reference them from main.qosm with qualified names:
// In main.qosm — no imports needed
let heal _ =
// ...
match diagnose errors with (
| Ok{value: d} ->
let _ = log {message: Helpers.format_diagnosis d} in
match Helpers.is_actionable d with (
| true -> create_issue d
| false -> Ok{value: "No action needed"})
// ...
Modules are file-based — helpers.qosm becomes Helpers. No import statements.
Run it end-to-end
In the workspace:
- Switch to the Home view to see the call graph — you'll see
healcallingget_errors,diagnose, andcreate_issue, with dashed lines to the capability externs. - Click heal in the function list or graph.
- Click Run. The agent fetches the health endpoint, diagnoses any errors, and (if warranted) creates a GitHub issue.
Publish and call from your app
Once it works, publish it:
- Click Publish in the editor toolbar
- Your agent is now available at
@yourusername/self_healer
Call it from Python:
from qosm import QosmClient
client = QosmClient()
q = client.project("@yourusername/self_healer")
result = q.heal()
print(result)
Or TypeScript:
import { AsyncQosmClient } from "@qosm/mcp-client";
const client = new AsyncQosmClient();
const q = await client.project("@yourusername/self_healer");
const result = await q.callFunction("heal", []);
What we built
A self-healing agent that:
- Monitors a service via HTTP (scoped to one domain)
- Diagnoses errors with structured LLM output (typed, verified)
- Fixes issues by creating GitHub issues (scoped to one repo)
- Has a visible, auditable security boundary — three capabilities, three effects, nothing more
The compiler guaranteed all of this before a single line executed. That's Qosm.
What's next
- Workspace — Deeper dive into the editor, call graph, and function dashboard
- SDKs — Call your agents from Python, TypeScript, or any MCP client
- Built-in Functions —
map,filter,foldl,parse_json,and_then, and more - Language Reference — Full syntax when you need the details