Skip to main content
Version: 1.0.0

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​

Terminal
mkdir -p pure-imports/src/examples
cd pure-imports
src/examples/common.tb
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​

src/examples/search.tb
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​

Terminal
touba prepare --profile dev --mode write

Expected result:

  • project AIR resolves SearchRequest, DefaultRows, and NormalizeQuery;
  • no manifest is created when no tool is declared;
  • no grant, secret, handler, or memory scope is added by import.

4. Inspect Prepared AIR​

Terminal
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 by callable_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​

Terminal
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");'