STAGE 3 / Projects and tooling · LESSON 17
Why this exists
Kujo has a broad native library. Memorizing names is less useful than knowing how to discover a function's actual contract. A plausible name or familiar equivalent from another language is not sufficient evidence.
Read the inventory
The standard-library table records signatures, arity, return types, error behavior, capability gates, and examples. Some rows say handler-defined; inspect the handler and its tests when the table does not specify enough detail. This is especially important for network, database, and process APIs.
Major families include strings and collections; files and paths; JSON, TOML, YAML, and CSV; hashing and crypto; HTTP and sockets; processes and environment; databases; asynchronous helpers; formatting and inspection; and the AI mechanisms covered later.
Four questions
Before using a native operation, answer: What arguments are accepted? What exact shape comes back? How is failure represented? What authority does it require? Then run a minimal example and an invalid-input drill.
The example parses a small JSON document, selects a field, and serializes a deliberate result. parse_json accepts JSON root values, not just dictionaries, so a successful parse alone does not establish that the result has the expected structure. Stage 5 introduces schema validation as a general boundary tool.
Professional pattern
Wrap a native operation only when the wrapper adds a real application policy: input limits, a stable domain result, or an explicit retry decision. Avoid layers that merely rename every builtin; they obscure the canonical contract and multiply documentation work.
Common mistakes
Display output and JSON serialization are not interchangeable. A runtime struct may print but fail to_json. Invalid JSON is an error, not an empty dictionary. Capability-free parsing does not make arbitrary parsed data trustworthy. It only tells you that parsing itself performs no host effect.
Working example
let data := parse_json(to_json({"items": [2, 3]}))
assert_equal(len(data["items"]), 2)
print(to_json({"count": len(data["items"])}))
Run it
From the course repository root, use the pinned Kujo 1.3.1 runtime.
kujo check examples/17.kujo
kujo run --untrusted examples/17.kujo
Captured output
{"count":2}
Break it and diagnose it
The text is malformed JSON. The native parser returns a real parse-location failure instead of silently producing empty data.
print(parse_json("{broken"))
kujo run --untrusted examples/17-break.kujo
Exit status: 4. Captured diagnostic:
[KUJOVM001] [vm] Runtime Error: JSON parse error: key must be a string at line 1 column 2
--> 0:0
Exercise
Choose one string helper and one filesystem helper from the inventory. Record their arity, result, failure, and capability. Write a valid and invalid call for each, using a fixture for the filesystem case.
Checkpoint
- I consult the canonical builtin inventory.
- I distinguish parsing from validation.
- I know how to inspect handler-defined contracts.
Verified 2026-09-06 · Official Kujo 1.3.1 release · Source contract · Download example