Paradigm Transitions Toward Touba
A new paradigm does not make previous languages incapable. A Python, Java, or TypeScript program can call a model, control a secret, write a trace, or limit an access path.
The difference is where the complexity lives. Each paradigm moves part of that complexity into a more legible abstraction. Touba extends this movement to agentic systems: agent responsibility, tools, secrets, memory, human validation, and traces become explicit program contracts instead of dispersed conventions.
The examples below are pedagogical. They show the same question through four styles:
| Step | Language Used | What It Highlights |
|---|---|---|
| Imperative script | Python | action order is direct and quick to read |
| Object-oriented | Java | responsibilities become named objects and services |
| Typed functional style | TypeScript | transformations and types make boundaries more visible |
| Probabilistic Agentic Programming with Touba | Touba | autonomy, authority, handlers, and traces become program artifacts |
Case 1 - External Content or Agentic Instruction
Question: a web page contains text that looks like an instruction. How can a program avoid treating it as a command addressed to the agent?
Imperative Python
def answer_from_page(url: str) -> str:
source_text = {
"kind": "external_content",
"content": fetch_url(url),
}
instruction = review_and_build_instruction(source_text)
return call_llm(instruction)
Python can handle the problem with clear discipline: name source_text, call a
review step, then call the model.
Application responsibility: the boundary depends on code conventions. Nothing prevents
another call path from sending source_text["content"] directly to the model.
Object-Oriented Java
final class SourceText {
private final String content;
SourceText(String content) {
this.content = content;
}
String content() {
return content;
}
}
final class AgentInstruction {
private final String content;
private AgentInstruction(String content) {
this.content = content;
}
static AgentInstruction fromReviewedSource(SourceText source, HumanReview review) {
review.requireAccepted();
return new AgentInstruction("Summarize this reviewed source: " + source.content());
}
String content() {
return content;
}
}
Objects absorb part of the complexity: SourceText and AgentInstruction are no
longer interchangeable strings. Building an instruction goes through a named
method.
Application responsibility: the actual model call, secrets, authority, and trace still live in host code or surrounding frameworks.
Typed Functional TypeScript
type SourceText = Readonly<{
kind: "external_content";
content: string;
}>;
type AgentInstruction = Readonly<{
kind: "agent_instruction";
content: string;
reviewedBy: string;
}>;
const buildInstruction = (source: SourceText, reviewedBy: string): AgentInstruction => ({
kind: "agent_instruction",
content: `Summarize this reviewed source: ${source.content}`,
reviewedBy,
});
const callLlm = async (instruction: AgentInstruction): Promise<string> => {
return await llm(instruction.content);
};
The typed functional style absorbs another part of the complexity: the
transformation becomes an explicit function, and callLlm expects an
AgentInstruction, not arbitrary text.
Application responsibility: TypeScript helps during development, but execution, permissions, manifest, secrets, and structured traces still need to be organized elsewhere.
Touba
module examples.boundary
type SourceRequest
url is Text
type SourceText
content is Text
type AgentInstruction
content is Text
type LLMAnswer
content is Text
tool FetchExternalContent
takes request as SourceRequest
gives SourceText
requires network
tool BuildAgentInstruction
takes source as SourceText
gives AgentInstruction
tool CallLLM
takes instruction as AgentInstruction
gives LLMAnswer
requires network, secret_read
secrets LLM_API_KEY
skill AnswerWithReviewedSource
takes request as SourceRequest
gives LLMAnswer
uses FetchExternalContent
uses BuildAgentInstruction
uses CallLLM
do
FetchExternalContent
with request as request
into source
human.review
with context as source
into review
BuildAgentInstruction
with source as source
into instruction
CallLLM
with instruction as instruction
into answer
give answer
Touba places the boundary in the program: external content, agentic instruction,
human review, the LLM tool, the secret, and requirements are visible in the
.tb contract.
What Touba absorbs: the runtime can refuse an undeclared handler, an ungranted secret, or an incompatible payload before the call. The trace can then show steps and refusals without becoming a complete prompt log.
Scope: this separation makes confusion more visible, testable, and auditable. The security model extends this foundation with payload policies, external validation, and observability integrations.
Case 2 - Real Tool, Secret, and Access Right
Question: an agent must call an external service with a key. Where should the network and secret requirements be declared?
Imperative Python
import os
def summarize(query: str) -> str:
api_key = os.environ["LLM_API_KEY"]
search_result = search_web(query)
return call_llm(api_key=api_key, text=search_result["text"])
The script is compact. The developer immediately sees the execution order.
Application responsibility: network access, the secret, key policy, timeout, payload size, and audit are details to maintain in code or in the environment.
Object-Oriented Java
final class SummarizeService {
private final SearchClient searchClient;
private final LlmClient llmClient;
private final SecretProvider secrets;
SummarizeService(SearchClient searchClient, LlmClient llmClient, SecretProvider secrets) {
this.searchClient = searchClient;
this.llmClient = llmClient;
this.secrets = secrets;
}
Summary summarize(String query) {
SearchResult result = searchClient.search(query);
String apiKey = secrets.resolve("LLM_API_KEY");
return llmClient.summarize(apiKey, result.text());
}
}
The object absorbs wiring complexity: dependencies become explicit in the constructor, and the service carries a readable responsibility.
Application responsibility: the language does not know that LLM_API_KEY is an
agentic handle, that searchClient requires network, or that this service may
only be called by specific agents.
Typed Functional TypeScript
type Capability = "network" | "secret_read";
type SecretHandle = "LLM_API_KEY";
type Binding = Readonly<{
grants: readonly Capability[];
secrets: readonly SecretHandle[];
}>;
const requireBinding = (binding: Binding): void => {
if (!binding.grants.includes("network")) throw new Error("network grant missing");
if (!binding.grants.includes("secret_read")) throw new Error("secret grant missing");
if (!binding.secrets.includes("LLM_API_KEY")) throw new Error("secret handle missing");
};
const summarize = async (query: string, binding: Binding): Promise<string> => {
requireBinding(binding);
const source = await searchWeb(query);
return await callLlm("LLM_API_KEY", source.text);
};
Types make capabilities and handles more legible. The check becomes a separate, testable function.
Application responsibility: this discipline remains in the TypeScript code. It does not automatically create AIR, a manifest, a shared runtime refusal, or a shared trace surface.
Touba
module examples.secure_tool
type SearchRequest
query is Text
type SearchResult
text is Text
type Summary
text is Text
tool SearchWeb
takes request as SearchRequest
gives SearchResult
requires network
tool SummarizeWithLLM
takes result as SearchResult
gives Summary
requires network, secret_read
secrets LLM_API_KEY
skill BuildSummary
takes request as SearchRequest
gives Summary
uses SearchWeb
uses SummarizeWithLLM
do
SearchWeb
with request as request
into result
SummarizeWithLLM
with result as result
into summary
give summary
agent Analyst
responsibility "Fulfill the declared Analyst responsibility using only authorized capabilities."
uses BuildSummary
callable_by strategy RunSummary
strategy RunSummary
uses Analyst
do
Analyst
Touba separates the handler contract. The program states that SearchWeb
requires network, and that SummarizeWithLLM requires network,
secret_read, and the LLM_API_KEY handle. The manifest must then grant these
elements explicitly to the runtime.
What Touba absorbs: the right to call a handler is not only a service
convention. It becomes a relation between .tb source, AIR, manifest, runtime,
and trace.
Scope: manifest grants express Touba authority at the execution-contract level. System controls, network controls, and handler dependency controls remain explicit host and supply-chain responsibilities.
Case 3 - Memory and Auditability
Question: an agent reads project memory. How can a team know who read what, with which logical right, and where the access is observed?
Imperative Python
trace = []
def answer_with_memory(question: str) -> str:
trace.append({"event": "memory_read_requested", "query": question})
note = memory_read(question)
trace.append({"event": "memory_read_completed"})
return call_llm(f"Answer with project context: {note}")
The script can produce readable events.
Application responsibility: trace, memory, access right, and prompt handling are conventions that every function must respect.
Object-Oriented Java
final class AuditedMemory {
private final MemoryRepository repository;
private final AuditLog auditLog;
AuditedMemory(MemoryRepository repository, AuditLog auditLog) {
this.repository = repository;
this.auditLog = auditLog;
}
MemoryNote read(String agentName, String query) {
auditLog.record("memory_read_requested", agentName);
MemoryNote note = repository.read(query);
auditLog.record("memory_read_completed", agentName);
return note;
}
}
The object absorbs audit responsibility around the repository. Domain code can
read AuditedMemory instead of calling the backend directly.
Application responsibility: the language does not force every access to go through this object. The link between agent, scope, backend, and trace depends on the application architecture.
Typed Functional TypeScript
type TraceEvent = Readonly<{ name: string; actor: string }>;
type MemoryNote = Readonly<{ content: string }>;
type RunState = Readonly<{ trace: readonly TraceEvent[] }>;
const addTrace = (state: RunState, event: TraceEvent): RunState => ({
trace: [...state.trace, event],
});
const readMemory = async (
state: RunState,
actor: string,
query: string,
): Promise<readonly [RunState, MemoryNote]> => {
const started = addTrace(state, { name: "memory_read_requested", actor });
const note = await memoryRead(query);
const completed = addTrace(started, { name: "memory_read_completed", actor });
return [completed, note];
};
The functional style makes trace state explicit: reading memory also returns a new run state. Implicit mutation is reduced in typed code.
Application responsibility: the program carries scope rules, grants, memory binding, and the shared trace format itself.
Touba
module examples.memory_audit
define MemoryQuestion as Text = "incident policy"
type MemoryNote
content is Text
memory ProjectKnowledge
tool ReadProjectKnowledge
uses memory ProjectKnowledge read
takes query as Text
gives MemoryNote
requires memory_read
skill ReadContext
gives MemoryNote
memory ProjectKnowledge read
uses ReadProjectKnowledge
do
ReadProjectKnowledge
with query as MemoryQuestion
into note
give note
agent RiskAnalyst
responsibility "Fulfill the declared RiskAnalyst responsibility using only authorized capabilities."
memory ProjectKnowledge read
uses ReadContext
callable_by strategy RunMemoryCheck
strategy RunMemoryCheck
uses RiskAnalyst
do
RiskAnalyst
Touba places memory in the agentic contract. Memory is logical, the tool
declares read access, the agent declares its scope, and the runtime checks
these elements against the manifest before calling the handler.
What Touba absorbs: auditability does not depend only on a hand-written logger. Authorized or refused accesses can be connected to AIR, manifest, the active agent, and the trace.
Scope: Touba governs logical access, provenance, and traces. Memory backends, content verification, and handler audit remain explicit integration responsibilities.
What the Transition Shows
| Transition | Added Abstraction | Complexity Absorbed |
|---|---|---|
| Imperative to object-oriented | named responsibilities | grouping state, behavior, and dependencies |
| Object-oriented to typed functional | explicit transformations and types | reducing implicit mutation and making boundaries visible |
| Typed functional to Touba | executable agentic contract | connecting agents, tools, secrets, memories, validations, and traces to the runtime |
Touba's value is not that it makes possible what other languages cannot do. Its value is to give first-class program status to responsibilities that, in earlier paradigms, often remain spread across host code, configuration, team discipline, and documentation.
In practice, those responsibilities often look like this:
| Usual Location | Example Responsibilities |
|---|---|
| Host code | verify that a handler receives the right payload, apply a timeout, avoid sending a secret value to a prompt, write audit events in the right place |
| Configuration | connect a tool to a handler, grant network or secret_read, choose the secret profile, set execution limits |
| Team discipline | avoid passing external content directly as instruction, request human review before a sensitive conversion, keep handlers small and reviewed |
| Documentation | explain which agent can call which other agent, which secret is used by which tool, which memory may be read, which trace proves a refusal or validation |
Touba does not remove these responsibilities. It moves them closer to the
program: they become more visible in .tb source, AIR, manifest, runtime, and
traces.
Verification Sources for External Examples
- Python: official documentation on functions and control flow, docs.python.org.
- Java: Oracle's official tutorial on objects, classes, and methods, object concepts and classes.
- TypeScript: official handbook on types, functions, and
readonlyproperties, everyday types, functions, and object types.