danielhuber.dev@proton.me Sunday, April 5, 2026

Typed Agent Workflows: Logical Transduction Algebra for LLM Pipelines

How formalizing LLM calls as typed semantic transformations with algebraic composition operators produces more predictable, debuggable, and maintainable agentic data workflows.


March 5, 2026

Building reliable agentic workflows often feels like assembling software out of fog: LLM calls accept arbitrary strings, return unstructured text, and glue together through ad-hoc parsing logic that breaks at the edges. A typed, algebraic approach to composing LLM calls treats each inference step as a formal transformation with known input and output types, making workflows provably composable, easier to test, and dramatically simpler to debug.

The Core Problem: Untyped LLM Pipelines

Most agent frameworks today treat LLM calls as black boxes — a string goes in, a string comes out, and the orchestration layer hopes for the best. This works well enough for demos but creates real engineering pain in production. When a downstream step expects structured JSON but the model returns a conversational reply, you get a runtime exception deep in a workflow that’s hard to trace back to its source. When you want to reuse a summarization step across two different pipelines, you discover it has implicit expectations baked into its prompt that aren’t visible from the outside.

The underlying issue is the absence of a type discipline. Traditional software engineering solved this problem with type systems: functions declare what they accept and what they return, compilers verify compatibility at composition boundaries, and engineers can reason about systems without running them. Applying the same discipline to LLM-based pipelines means treating each inference call as a typed semantic transformation — a function from a structured input type to a structured output type, where the “computation” is performed by the language model interpreting a prompt.

Transductions as First-Class Typed Objects

The key conceptual shift is modeling each LLM call as a transduction: a mapping from one semantic domain to another. A sentiment analysis step is a transduction from Document to SentimentScore. An entity extraction step is a transduction from RawText to List[Entity]. A question-answering step is a transduction from (Context, Question) to Answer.

When transductions are first-class typed objects, the framework can enforce compatibility at the point where two steps are joined. If step A produces List[Entity] and step B expects Document, the composition fails at definition time, not at 3am when the pipeline runs on production data.

# Conceptual sketch of typed transduction composition
@transduction(input_type=RawText, output_type=List[Entity])
def extract_entities(text: RawText) -> List[Entity]:
    ...

@transduction(input_type=List[Entity], output_type=KnowledgeGraph)
def build_graph(entities: List[Entity]) -> KnowledgeGraph:
    ...

# Type-checked at definition time — only valid if extract_entities output
# matches build_graph input
pipeline = extract_entities >> build_graph

This is analogous to function composition in typed functional languages. The >> operator (or equivalent) checks that the codomain of the left transduction matches the domain of the right before any LLM call is ever made.

Note

Typed transductions don’t constrain what the model does — they constrain how steps connect. The model still generates free-form text internally; the framework parses and validates that output against the declared output type before passing it downstream.

Algebraic Operators for Workflow Construction

Beyond simple sequential composition, a transduction algebra provides a small set of combinators that cover the structural patterns common to real agentic workflows:

Sequential composition (A >> B) — pipe the output of A directly into B. Type-checked at definition time.

Parallel composition (A & B) — run A and B concurrently over the same input, collecting both outputs into a tuple type. Useful for running multiple extractors over a document simultaneously.

Conditional branching (A | B with a predicate) — route to A or B based on a typed condition over the input. Enables pipelines that take different paths based on document type or confidence score.

Map (map(A)) — apply transduction A to every element of a list input, returning a list of outputs. The natural primitive for batch processing.

Fold/reduce — aggregate a sequence of typed outputs into a single summary type, useful for synthesizing results across a multi-document retrieval stage.

Input (RawText)


┌─────────────┐
│  extract()  │  Transduction: RawText → List[Entity]
└─────────────┘
      │ List[Entity]
      ├──────────────────────────┐
      ▼                          ▼
┌──────────────┐        ┌─────────────────┐
│ build_graph()│        │ rank_salience()  │  Parallel composition
└──────────────┘        └─────────────────┘
      │ KnowledgeGraph          │ List[ScoredEntity]
      └──────────┬──────────────┘

         ┌─────────────┐
         │  summarize() │  Transduction: (KG, Scored) → Report
         └─────────────┘
               │ Report

            Output

Each operator composes transductions into larger transductions — the resulting pipeline is itself a typed object with a declared input type and output type, which means pipelines can be nested inside other pipelines without special handling.

Stateless Async Execution

An important constraint in this model is that transductions are stateless: each call takes its inputs, invokes the LLM, and returns outputs without side effects or dependency on external mutable state. This isn’t a limitation — it’s the property that makes the algebra work cleanly and that makes individual steps independently testable and retryable.

Statelessness pairs naturally with asynchronous execution. Because no transduction holds state between calls, parallel branches can be dispatched concurrently without coordination overhead. The framework can schedule the execution graph — determined entirely at definition time from the composition operators — onto an async runtime, maximizing throughput without requiring the developer to reason about concurrency.

Tip

For production systems, stateless transductions make retry logic trivial: any failed step can be re-executed with the same inputs without worrying about partial state corruption. Design your transductions to be pure functions of their typed inputs.

State that the workflow genuinely needs — conversation history, retrieved documents, accumulated results — should be carried explicitly in the input types rather than stored in global or instance variables. This makes data flow visible in the type signatures and eliminates a whole category of subtle bugs caused by stale context.

Practical Engineering Implications

Adopting a typed transduction approach changes how you write, test, and maintain agentic pipelines in concrete ways:

Testing becomes unit-testable. Because each transduction is a typed function, you can test it in isolation by providing sample inputs and asserting on the output type and content. No need to spin up the entire pipeline to verify that entity extraction works correctly on financial documents.

Debugging is localized. When a pipeline fails, the type system tells you exactly which composition boundary was violated. You don’t need to trace through logs to find where a string parsing assumption broke down — the failure is surfaced at the structural level.

Reuse is safe. A transduction that’s been tested against its declared types can be dropped into a new pipeline without auditing its internals for hidden assumptions. The type signature is the contract.

Explainability follows from structure. Because the workflow is defined as an explicit composition of named, typed steps rather than a nest of callbacks and prompts, you can generate a structural description of what the pipeline does from its definition alone — useful for auditing, documentation, and compliance.

The tradeoff is upfront investment in defining types. For exploratory prototyping, this feels like overhead. For pipelines that will run in production at scale, it pays dividends quickly — especially as requirements evolve and steps need to be swapped, extended, or composed into larger systems.

Tags: researcharchitecturetype-safetyworkflowcompositionprompt-engineering

This article is an AI-generated summary. Read the original paper: Agentics 2.0: Logical Transduction Algebra for Agentic Data Workflows .