Skip to main content
Open in Kaggle  Open in Colab  Download Notebook
This documentation page is also available as an interactive notebook. You can launch the notebook in Kaggle or Colab, or download it for use with an IDE or local Jupyter installation, by clicking one of the above links.
Two popular taxonomies describe the building blocks of agentic AI systems:
  • Cognitive / reasoning-oriented (Taxonomy 1): Reflection, Tool Use, ReAct, Planning, Multi-Agent — asks “how does the agent think?”
  • Architectural / system-design-oriented (Taxonomy 2): Prompt Chaining, Routing, Parallelization, Tool Use, Evaluator-Optimizer, Orchestrator-Worker — asks “how do you wire LLM calls together?”
(See OpenAI’s Practical Guide to Building Agents, Anthropic’s multi-agent research system, and Pydantic AI’s multi-agent delegation.) Mapping them against each other reveals:
The cleanest framing: six architectural patterns that describe how you structure LLM calls, plus two cross-cutting reasoning strategies (ReAct and Planning) that can be layered inside any of them. This cookbook implements all eight in Pixeltable, where your agent is a table:

Setup

Created directory ‘agentic_patterns’.
<pixeltable.catalog.dir.Dir at 0x32639cb90>

Pattern 1: Prompt Chaining

Break a complex task into sequential steps, where each step’s output feeds the next. Imperative approach: a chain of function calls or an explicit pipeline object. Pixeltable approach: each step is a computed column. The engine resolves dependencies automatically.
input → step 1 (outline) → step 2 (draft) → step 3 (polish) → output
Created table ‘chain’.
Added 0 column values with 0 errors in 0.00 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Inserted 1 row with 0 errors in 14.58 s (0.07 rows/s)
Every intermediate result (outline, draft, final_article) is persisted in the table. Inserting another topic reuses the same pipeline — no code changes needed. If the same topic is inserted again, cached results are returned instantly.

Pattern 2: Routing

Classify an input and route it to a specialized handler. This is the agent equivalent of a switch/case statement. Imperative approach: a triage agent that performs handoffs to specialized agents. Pixeltable approach: one computed column classifies; a UDF selects the prompt; a second LLM call generates the response.
input → classify intent → select specialized prompt → generate response
Created table ‘router’.
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Added 0 column values with 0 errors in 0.00 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Inserted 3 rows with 0 errors in 6.93 s (0.43 rows/s)
Each query was classified and then handled by a specialized system prompt. The intent column is inspectable for every row, making it easy to audit routing decisions.

Pattern 3: Parallelization

Run multiple independent LLM calls on the same input simultaneously, then combine the results. Imperative approach: asyncio.gather or thread pools. Pixeltable approach: add independent computed columns. The engine parallelizes them automatically because they share no dependencies.
         ┌→ sentiment  ─┐
input  ──┼→ entities   ──┼→ merge → combined output
         └→ summary    ─┘
Created table ‘parallel’.
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.00 s
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.00 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Added 0 column values with 0 errors in 0.01 s
No rows affected.
The three LLM calls (sentiment, entities, summary) have no dependency on each other, so Pixeltable dispatches them concurrently. The merge_analysis UDF waits for all three before combining the results. No async code required.

Pattern 4: Tool Use

Give an LLM access to external functions it can call to gather information or take action. Imperative approach: @function_tool decorator, tool loop that re-prompts until the LLM stops requesting tools. Pixeltable approach: pxt.tools() bundles UDFs into tool definitions; invoke_tools() executes the LLM’s choices — both as computed columns.
input → LLM (with tools) → invoke_tools() → results
For a deeper walkthrough including MCP servers, see Use tool calling with LLMs.
Created table ‘tool_agent’.
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
The LLM chose which tools to invoke (including multiple tools for the last query). invoke_tools() executed them and stored results. The full LLM response is also persisted in the response column for debugging.

Pattern 5: Evaluator-Optimizer

One LLM generates output, a second LLM evaluates it, and the results are used to decide whether to refine. This is the architectural cousin of the Reflection pattern from Taxonomy 1 — an agent critiques its own output and iteratively improves it. Imperative approach: a while-loop that re-prompts until a quality threshold is met (see Pixelagent’s reflection example). Pixeltable approach: chained computed columns — generate, evaluate, then conditionally refine. The evaluation score is stored alongside the content for analysis.
input → generate → evaluate (score + feedback) → refine if needed → output
Created table ‘evaluator’.
Added 0 column values with 0 errors in 0.00 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Inserted 2 rows with 0 errors in 2.95 s (0.68 rows/s)
Both the first draft and the refined version are stored side-by-side with the evaluation. This makes it straightforward to compare outputs, audit the judge’s reasoning, or filter rows where the score fell below a threshold.

Pattern 6: Orchestrator-Worker

A central agent decomposes a task, delegates sub-tasks to specialized worker agents, and synthesizes the results. This is the architectural cousin of the Multi-Agent pattern from Taxonomy 1, and the same structure Anthropic uses in their multi-agent research system — a lead agent coordinates parallel subagents, each with their own context and tools. Imperative approach: an orchestrator agent class that spawns worker agent instances and collects their outputs. Pixeltable approach: each worker is a table with computed columns, wrapped as a callable function via pxt.udf(table, return_value=...). The orchestrator table calls these functions as computed columns.
input → decompose → worker A (summarizer)  ─┐
                  → worker B (fact-checker) ─┼→ synthesize → output
For more on table UDFs, see Use a table pipeline as a reusable function.

Build worker agents as tables

Created table ‘summarizer’.
Added 0 column values with 0 errors in 0.10 s
Added 0 column values with 0 errors in 0.06 s
Created table ‘checker’.
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.02 s

Build the orchestrator

Created table ‘orchestrator’.
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Added 0 column values with 0 errors in 0.02 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Inserted 1 row with 0 errors in 4.69 s (0.21 rows/s)
The orchestrator table called two independent worker pipelines (summarize and fact_check), each backed by their own table with full intermediate-result persistence. The synthesis step consumed both outputs to produce the final briefing. Adding a new worker (e.g., a tone analyzer) requires only creating another table, wrapping it with pxt.udf(), and adding one more computed column to the orchestrator.

Strategy A: ReAct

ReAct is not a wiring pattern — it is a reasoning strategy that can be applied inside any of the six patterns above. The agent alternates between reasoning about the next step and acting on it (typically via tools), observing the result before deciding what to do next. Imperative approach: a while-loop that parses the LLM’s THOUGHT/ACTION output, calls tools, and feeds observations back (see Pixelagent’s ReAct example). Pixeltable approach: the reasoning loop lives in a UDF that inserts rows into a tool-calling table and reads back results. The table stores every thought-action-observation triple for full observability.
question → [THOUGHT → ACTION → OBSERVATION] × N → final answer
Created table ‘react_steps’.
Added 0 column values with 0 errors in 0.00 s
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.00 s
No rows affected.
Every thought, action, and observation is persisted as a row in the react_steps table. The loop itself is plain Python; the LLM calls and tool execution happen declaratively via computed columns. This makes the reasoning trace fully queryable after the fact — useful for debugging or evaluation.

Strategy B: Planning

Planning is the second cross-cutting reasoning strategy. Instead of acting step-by-step (ReAct), the agent first generates a complete plan, then executes each step. This is especially effective for complex tasks where the structure of the solution can be determined upfront. Imperative approach: an LLM generates a plan as structured JSON, then a loop executes each step (see Pixelagent’s planning example). Pixeltable approach: a prompt-chaining pipeline where the first column generates the plan and a UDF parses it into executable steps. Each step then feeds into subsequent computed columns.
question → generate plan → execute step 1 → execute step 2 → … → synthesize
Created table ‘planner’.
Added 0 column values with 0 errors in 0.00 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Added 0 column values with 0 errors in 0.01 s
No rows affected.
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.01 s
Added 0 column values with 0 errors in 0.01 s
No rows affected.
The plan (stored in plan_steps) is fully inspectable. The execution step answers all sub-questions in a single LLM call, but this could also use parallelization (Pattern 3) to answer each sub-question independently and merge the results. Planning and ReAct compose naturally with any of the six architectural patterns.

Choosing a Pattern

Six architectural patterns

Two cross-cutting reasoning strategies

Patterns compose naturally. An orchestrator-worker system might use routing in the orchestrator, tool use within a worker, and ReAct reasoning inside the tool-calling loop. Because each pattern is just a set of computed columns on a table, combining them requires no special glue code.

See Also

Pixeltable cookbooks: Pixelagent examples (imperative implementations of the same patterns):
  • Reflection loop — main agent + critic agent with iterative refinement
  • ReAct / Planning — step-by-step reasoning with tool calls
  • Tool calling — OpenAI, Anthropic, and Bedrock tool integration
  • Memory — persistent and semantic memory management
External references:
Last modified on June 24, 2026