Skip to main content

Cookbook

Each recipe here is a real problem, solved end to end: the Stof document, which you can run on the page, and the app code around it. Every one comes down to the same thing: logic that changes more often than your app, or comes from somewhere other than your codebase, as data your app can check and run safely.

Recipes​

Logic from AI models

  • Run Rules a Model Writes: turn a plain-English policy into code with a model, check it against tests and real examples, and run it on every request with no model call.
  • Agent Tools at Runtime: tools as Stof functions, tool definitions generated from them, and an agent that writes new tools mid-conversation, all sandboxed.

Logic your customers and teams change

Data and logic that travel

Patterns You'll See​

The recipes share a handful of patterns. Once you know them, most new uses are a combination.

The attribute is the contract​

Your app runs functions by attribute: #[route], #[approval], #[flag], #[tool]. Whoever writes the logic (a model, a customer, another team) can add as many functions as they need, with any names, and your app finds them with funcs(attributes = 'route') or doc.run('route'). See Attributes.

Your app owns a small harness​

The part that runs the untrusted part is a few lines your app writes: take the input, call every tagged function, return the result. The recipes call it route, evaluate, normalize, and call_tool. It keeps the contract in one place, and the logic you accept never has to know how it's called.

Maps in, maps out​

Your app passes plain objects (a JavaScript object or a Python dict), which arrive as maps. The harness turns one into an object with Obj.from_map, declares it with using so it's cleaned up afterward, and returns a map or JSON. Nothing piles up in a long-lived document.

Your functions are the only door​

A document can't reach files, the network, or your app unless you give it a way. Give it specific functions with doc.lib(..), scoped to the current customer or request, and put your limits inside them (like "refunds over $100 need a person"), because new logic can call them too. See What a Document Can Reach.

Check before you trust​

Logic from outside goes through checks before it's live: it parses, its own #[test] functions pass, it agrees with examples you know the answer to, and its output fits a #[schema]. Every failure is a plain message with a line number, which a model can fix and a person can read.

Logic ships as data​

Binary Stof (bstf) holds logic and data together. Publish a new document, and every service and browser swaps it in: new plans, flags, rules, or mappings, with no release. Keep the source in version control with tests, and publish from CI.

Every call has a time limit​

Set one with setMaxExecutionTime, sized to the job: tens of milliseconds for a check on every request, seconds for an agent's tool. A runaway loop fails that one call, and nothing else.