Tutorial - Organize a Project with Pure Imports
Goal: split a Touba project into multiple modules without creating implicit runtime authority.
Pure imports (IM-1) cover only type, non-sensitive define, and pure
function.
Local imports of tool, skill, strategy, agent, and memory exist in the
effectful slice of the same project. This tutorial focuses on sharing pure code.
1. Create the Common Module
mkdir -p pure-imports/src/examples
cd pure-imports
module examples.common
type SearchRequest
query is Text
rows is Int
define DefaultRows as Int = 5
function NormalizeQuery
takes query as Text
gives Text
do
give query
2. Create the Application Module
module examples.search
import type SearchRequest from examples.common
import define DefaultRows from examples.common
import function NormalizeQuery from examples.common
function BuildLabel
takes request as SearchRequest
gives Text
do
NormalizeQuery
with query as request.query
into normalized
give normalized ++ ":" ++ text(DefaultRows)
strategy RunLabel
takes request as SearchRequest
gives Text
uses BuildLabel
do
BuildLabel
with request as request
into label
give label
Imports are placed after module and before declarations.
3. Prepare the Project
touba prepare --profile dev --mode write
Expected result:
- project AIR resolves
SearchRequest,DefaultRows, andNormalizeQuery; - no manifest is created when no
toolis declared; - no grant, secret, handler, or memory scope is added by import.
4. Inspect Prepared AIR
touba inspect .touba/build/dev/air/examples/search.air.json
You should see imports and their resolution status.
5. Move to Imports with Runtime Authority
A pure import never creates a manifest, handler, grant, secret, caller, or memory scope. When composing tools, agents, strategies, or memories across modules, use the multi-module import guide:
- imported
tool: the manifest binding remains on the canonical reference of the declaring module; - imported
agent: the caller must be explicitly authorized bycallable_by; - imported
memory: the owner must declare the required scope before calling an access tool.
Validated Contract
Pure imports (IM-1) cover the pure part of the language:
- sharing types;
- sharing non-sensitive constants;
- sharing pure functions;
- assembling these elements in project AIR;
- diagnosing ambiguous or missing imports.
The goal is to structure pure code without moving execution authority. The
multi-module import guide covers tool, skill, strategy, agent, and
memory cases. The rule remains the same: an import makes a component visible,
while the project explicitly binds manifest, handler, secrets, constraints,
scopes, callers, lock, and runtime authority when required.
Execute and verify
touba run .touba/build/dev/air/examples/search.air.json \
--entry strategy:examples.search/RunLabel \
--inputs-json '{"request":{"query":"parks","rows":2}}' --output json > result.json
node --input-type=module -e 'import assert from "node:assert/strict"; import {readFileSync,existsSync} from "node:fs"; const r=JSON.parse(readFileSync("result.json")); assert.equal(r.status,"success"); assert.equal(r.result,"parks:5"); assert.equal(existsSync("touba.manifest.json"),false); console.log("PURE_IMPORTS_EXECUTED_WITHOUT_RUNTIME_GRANTS");'