Skip to content

Composition Patterns

Rotifer provides a formal gene algebra for composing simple genes into complex behaviors. This is one of the key differentiators from traditional skill/tool systems — compositions are type-safe, verifiable, and automatically optimizable.

Execute genes one after another, piping the output of each gene as input to the next.

Seq(A, B, C) = A → B → C
import { Seq } from "@rotifer/algebra";
const pipeline = Seq(
"genesis-web-search", // Step 1: Search the web
"text-summarize", // Step 2: Summarize results
"text-translate" // Step 3: Translate summary
);
// Input flows: search → summarize → translate
const result = await pipeline.execute({
query: "quantum computing breakthroughs"
});

Data flow: Output of gene N becomes input of gene N+1. Schemas must be compatible (output of A must satisfy input of B).

Execute genes concurrently and collect all results. Uses true CPU parallelism via thread pool.

Par(A, B, C) = A ‖ B ‖ C → [resultA, resultB, resultC]
import { Par } from "@rotifer/algebra";
const multiSearch = Par(
"genesis-web-search", // Search provider 1
"genesis-web-search-lite", // Search provider 2
"academic-search" // Academic sources
);
// All three run simultaneously
const results = await multiSearch.execute({
query: "rotifer protocol"
});
// results = [searchResult1, searchResult2, academicResult]

Use cases:

  • Fan-out queries to multiple data sources
  • Redundant execution for fault tolerance
  • Independent subtask parallelism

Choose which gene to execute based on a runtime predicate.

Cond(predicate, thenGene, elseGene)
import { Cond } from "@rotifer/algebra";
const smartSearch = Cond(
(input) => input.query.length > 100, // Long query?
"deep-research-gene", // Yes: deep research
"genesis-web-search" // No: quick search
);

Use cases:

  • Route requests based on input characteristics
  • A/B testing between gene implementations
  • Graceful degradation based on resource availability

Execute a primary gene; if it fails, fall back to a secondary gene.

Try(primary, fallback) = primary ?? fallback
import { Try } from "@rotifer/algebra";
const resilientSearch = Try(
"premium-api-search", // Try premium API first
"genesis-web-search" // Fall back to free search
);

Behavior:

  • If primary succeeds → return primary result
  • If primary throws → execute fallback, return fallback result
  • If both fail → propagate the fallback error

Apply a transformation function between genes to reshape data.

Transform(gene, mapFn) = gene → mapFn(result)
import { Transform, Seq } from "@rotifer/algebra";
const pipeline = Seq(
"genesis-web-search",
Transform((searchResult) => ({
text: searchResult.results.map(r => r.snippet).join("\n"),
maxLength: 200
})),
"text-summarize"
);

Pattern 1: Search → Summarize → Translate Pipeline

Section titled “Pattern 1: Search → Summarize → Translate Pipeline”
const researchPipeline = Seq(
"genesis-web-search",
Transform((r) => ({ text: r.results[0].snippet })),
"text-summarize",
Transform((r) => ({ text: r.summary, targetLang: "zh" })),
"text-translate"
);

Pattern 2: Parallel Search with Aggregation

Section titled “Pattern 2: Parallel Search with Aggregation”
const multiSourceSearch = Seq(
Par(
"web-search",
"academic-search",
"code-search"
),
Transform((results) => ({
text: results.flat().map(r => r.title).join(", ")
})),
"text-summarize"
);

Pattern 3: Resilient Pipeline with Fallbacks

Section titled “Pattern 3: Resilient Pipeline with Fallbacks”
const robustPipeline = Seq(
Try("premium-search", "free-search"),
Try("gpt4-summarize", "local-summarize"),
"text-translate"
);
const adaptivePipeline = Seq(
"genesis-web-search",
Cond(
(r) => r.results.length > 10,
"deep-analysis-gene", // Many results: analyze deeply
"quick-summary-gene" // Few results: quick summary
)
);

The composition algebra enforces type compatibility at composition time:

  • Seq(A, B) requires A.outputSchema ⊇ B.inputSchema
  • Par(A, B) requires A.inputSchema = B.inputSchema
  • Cond(p, T, F) requires T.outputSchema = F.outputSchema
  • Try(P, F) requires P.outputSchema = F.outputSchema

Incompatible compositions produce compile-time errors:

Error[E0032]: Type mismatch in Seq composition
→ gene 'web-search' output: { results: SearchResult[] }
→ gene 'translate' input: { text: string, targetLang: string }
help: Add a Transform between the genes to reshape the data

Composed genes inherit fitness from their components:

  • Seq — F(Seq) = min(F(components)) × latency_penalty
  • Par — F(Par) = avg(F(components)) × parallelism_bonus
  • Try — F(Try) = F(primary) × success_rate + F(fallback) × (1 - success_rate)

The Arena evaluates compositions as a whole, creating selection pressure for efficient composition structures.