I shared a public account of HCAN as a condensed language for human–agent communication. Its grammar helps a person name an intent, a source, a return shape, and a guard without hiding the boundary in a paragraph. Alongside it I have been building Sigil, a different language: a checked S-expression language for programming agentic systems. HCAN is not Sigil syntax, and Sigil does not replace human conversation.
The article’s original account reported that a Sigil program made an admitted call to a local language model, received a typed answer, checked it, and recorded a receipt. The cited private implementation and return record were not available for this review, so I cannot independently verify that run or treat it as evidence of current runtime behavior. I can still explain the design seam: what a program declares before delegation, and what its records can establish afterward.
Four reference forms with different jobs
HCAN’s current syntax distinguishes four reference forms. An @ reference binds an accountable source or location; it is the only source-bound form. A $ reference names a concept: an idea that can be compared or discussed without pretending it is a file. A ~ reference marks an approximation. An &name reference dereferences a let-bound variable that is in scope; it is not a source locator. A name for an idea is useful, but it is not evidence for a claim about the world. A line with only concept, approximation, or variable references still needs an accountable source binding when the task makes a source-grounded claim.
For example, this validated read-only comparison keeps a named idea, a deliberately approximate neighbor, and its actual source locator separate. It shows the first three forms; it has no let-binding in scope, so it does not use &name:
compare $rag-retrieval ~vector-search-hybrid @research/notes :Brief ?tradeoffs !no-writeThe same insistence on distinctions has reached effects. Network and execute joined read, compute, and write as named effect classes. When tags combine, a closed rule table can record interactions: write × network becomes data-egress; read × network becomes data-ingress; execute × network becomes remote-execute. More recent structured bindings and scoped guards refine what those effects touch. These are descriptions and checks, not a self-issued permission slip. A tool’s ability to send data is different from the authority to send this data on this task.
The medium has also grown an opt-in vocabulary loader and a collection of multiline example programs. The core grammar stays small while particular domains can say more. I do not want to blur this work into a claim that HCAN is a runtime; it remains a communication medium with validators and editor surfaces.
Read three HCAN programs, not just a list of features
Here is a Set-B creative-constraint program from the evolving sample library. :Constraint and ?exhaustive require the opt-in hcan-creative-constraint vocabulary. The existing design and synth verbs do the work of describing a request; the vocabulary adds a shape and probe, not permission to write:
#[design-ideas] begin bounded-ideation
design @problem :Constraint -> map(must-have,must-avoid,freedom) ?exhaustive !no-write
synth @ideas :Vec<Card> -> map(approach,risk,falsifier) ?novelty !no-write
endThis program passed canonical HCAN compilation with that vocabulary enabled. Other Tier-1 Set-B additions include :Mechanic with ?balance for a game design and :Vibe with ?calibration for a tonal review. They are opt-in vocabulary surfaces, not new universal base verbs. The current syntax contract also lists counterfactual and branch, and the feature matrix records their B03 and B05 entries as implemented Tier-2 verbs. Those project records remain candidate and review-required; this page review did not independently run the compiler against those verbs. Other Set-B items remain at different proposal and implementation states, so an example should not be taken as evidence that the entire set is complete.
HCAN-Effect makes a more consequential distinction. The following line is deliberately rejected by the guard check. The two intent tags derive an interaction class, remote-execute; the guard forbids it. Its validation succeeds, but guard_compliance=false and the compiler records a violation:
#[test-x][transfer-y] begin guarded-work
orient @d :Brief ?gaps !no-remote-execute
endStructured effects add path-level evidence to the flat effect set. For example, transfer @sources/hub :Brief ?gaps !no-write(path:/sources) yields a write(sources/hub) binding that matches the scoped guard; a guard scoped to /tmp does not match that target. Neither a passing parse nor an effect record authorizes an external transfer.
HCAN-Stream uses ~> to connect a producer line to the next consumer within the block. With the base shapes below, canonical compilation passes and records one edge (producer line 2 → consumer line 3), plus produce(stream-2) and consume(stream-2) effect bindings:
begin pipeline
trace @logs :Brief -> filter(level=warn) ~>
inspect @filtered :Table -> aggregate(count-by-service) ?gaps !no-write
endThis is a dataflow description and compiler record, not a live log subscription or executed filtering job. HCAN’s trace, inspect, compare, synth, design, test, transfer, and return are different verbs with different implied effects and return purposes; treating all of them as a generic “ask the agent” would lose the point.
A program reaches the model
Sigil makes the next step executable under a separate set of conditions. A program defines a request record, a response sum, and a delegation schema. A function that delegates must declare the particular llm/Request effect. The checker rejects a missing declaration. At evaluation time, the schema needs an admitted capability and a matching route. A name in a provider registry alone grants nothing.
In schematic Sigil, the crossing looks like this:
(defrecord BonsaiRequest ((goal Text)))
(defdata BonsaiResponse (Ok Text) (Refused Text))
(delegation-schema BonsaiRequest BonsaiResponse)
; inside a function declaring (:effects (llm/BonsaiRequest)):
(match (delegate (record BonsaiRequest ((goal "Reply briefly"))))
((Ok answer) answer)
((Refused reason) reason))The abbreviated function body above illustrates the type and refusal shape; it is not a copy-paste standalone program or the exact live prompt. The original article reported that an owner-authorized canary used a local Bonsai 27B through obsidian-sglang, returned (Ok "bonsai is live"), and recorded outcome=provider-executed and deviation=none.
Current review note · 2026-10-01: This is a historical account of the run. The cited private commit and return receipt were not available in the source checkouts for this local review, so the canary is not independently reverified here. It does not establish current runtime behavior, answer correctness, task usefulness, safety, or provider reliability.
Refusal has its own ordinary branch. Backend failure is a different lane, with a typed error and an explicitly declared fallback where available. A policy stop is not a model refusal and cannot be wished away by matching on Refused. When a response fails its shape, deviation details identify the constructor or field at issue. The receipt’s digest is currently non-cryptographic; I would not use it as an integrity guarantee.
What Sigil itself can compute
Model delegation is only one Sigil effect. A pure program can destructure records and match a closed sum without a provider. This small case comes from the evaluator’s executable tests: it returns "hello" and needs no network route.
(defrecord Greeting ((message Text) (count Int)))
(defun read-message ((g Greeting)) (:returns Text)
(match g ((Greeting msg n) msg)))
(defun main () (:returns Text)
(read-message (record Greeting ((message "hello") (count 2)))))Extension packs make checked structures reusable. The graph pack’s test assembles an integer graph, list and DFS function via namespaced use forms, then checks a fuel-bounded search. The following is a complete tested program when the graph-utils pack is supplied; it returns true on the reachability fixture and neither calls a model nor grants an effect:
(use graph-utils/int-list IntList)
(use graph-utils/int-graph IntGraph)
(use graph-utils/int-member int-member IntList)
(use graph-utils/graph-neighbors neighbors IntGraph IntList)
(use graph-utils/graph-dfs dfs IntGraph IntList int-member neighbors)
(defun main () (:returns Bool)
(dfs (GEdge 1 2 (GNil)) 2 (LCons 1 (LNil)) (LNil) 4))HCAN also now has an A07 emitter that maps its compiled IR into Sigil-shaped S-expression source, including intent and guard annotations and comments for stream edges. That is a reviewable bridge candidate, not an executable conversion: its generated hcan:: calls are not yet bound to a checked Sigil implementation. The HCAN stream above therefore does not become a running Sigil task graph just because codegen prints it.
Why the toolchain stays outside the call
The reader, checker, formatter, and language server do not contact a model. That is a design boundary, not a lack of ambition. It means an editor can inspect a program offline without silently turning editing into execution. The evaluator can then delegate only under a named runtime admission. The same program can be checked without an available provider and evaluated only in an environment that has chosen its route and limits.
This is also where my confidence stops. The article reports offline tests of the reader, types, evaluation, routes, and mock transport; those test records were not re-audited as part of this page review. The one reported live canary is likewise historical and not independently reverified here. There is not yet evidence in this review for independent qualification of every provider, end-to-end aggregate budgets, or attenuation of authority per call site. The other registered providers remain pending adapters in the article’s cited account; they do not become live because they appear in a table. A structural response check is not a judgment that the answer is correct or useful.
HCAN can help a human say what kind of action is intended and what guard must hold. Sigil can check a bounded computation and produce evidence about an admitted effect. Neither language makes the human decision for us. The next useful experiment is to ask whether these explicit boundaries make a real task easier to review and correct than a simpler program or prompt. If they do not, the simpler route should win.
A review protocol for a model-calling program
For an agentic engineering task, inspect the call boundary in this order: declared request and response types; source and context passed to the model; route and capability admission; per-call and aggregate resource limits; refusal and transport-error branches; output validation; and the receipt linking execution to the exact program revision. Then ask which of those are implemented and tested in the current target, rather than inferred from the language design. A valid response shape is a type-level fact, not a truth check.
For an agentic research task, include a source-span requirement and an explicit unknown return when supplied evidence is insufficient. Evaluate with adversarial fixtures that contain conflicting papers, missing context, malformed outputs, and valid-looking unsupported claims. Proposal: compare the typed route with a simpler baseline on refusal quality, provenance retention, task success, latency, and review cost. The historical canary and project records described above do not answer that comparison.
AI assistance disclosure: AI assisted in assembling and drafting this public-safe update from project records. I direct the project and retain responsibility for reviewing the claims and publication.