Skip to content

Compose โ€‹

compose() and pipe() chain agents into sequential pipelines. The output text of each agent becomes the prompt for the next. No graph required.

ts
import { compose, pipe, createAgent } from 'confused-ai';

compose() โ€” simple pipeline โ€‹

ts
import { createAgent, compose } from 'confused-ai';

const researcher = createAgent({
  name: 'researcher',
  instructions: 'Research topics and return raw findings.',
  model: 'gpt-4o-mini',
  apiKey: process.env.OPENAI_API_KEY!,
});

const writer = createAgent({
  name: 'writer',
  instructions: 'Turn research findings into polished reports.',
  model: 'gpt-4o',
  apiKey: process.env.OPENAI_API_KEY!,
});

// Always pass researcher output โ†’ writer
const pipeline = compose(researcher, writer);
const result = await pipeline.run('Write a report on TypeScript 5.5');
// result.text โ€” the writer's final output

Conditional hand-off โ€‹

Use when to stop the pipeline early:

ts
const pipeline = compose(researcher, writer, {
  // Only hand off to writer if research is substantial
  when: (result) => result.text.length > 200,
});

Transform output between stages โ€‹

Use transform to reshape the output before passing it to the next agent:

ts
const pipeline = compose(researcher, writer, {
  transform: (result) => `Here are the research findings:\n\n${result.text}`,
});

pipe() โ€” fluent step-by-step builder โ€‹

ts
import { pipe } from 'confused-ai';

const draft   = createAgent({ name: 'drafter',   instructions: 'Draft a blog post.', ... });
const editor  = createAgent({ name: 'editor',    instructions: 'Edit for clarity.', ... });
const publish = createAgent({ name: 'publisher', instructions: 'Format for publication.', ... });

const pipeline = pipe(draft)
  .then(editor,  { transform: (r) => `Edit this draft:\n\n${r.text}` })
  .then(publish, { when: (r) => r.text.length > 50 });

const result = await pipeline.run('TypeScript 5.5 features');

Three-stage document pipeline โ€‹

ts
const summarizer = createAgent({ name: 'summarizer', instructions: 'Summarise this document in 3 bullet points.', ... });
const classifier = createAgent({ name: 'classifier', instructions: 'Classify the document: legal / technical / marketing.', ... });
const router     = createAgent({ name: 'router',     instructions: 'Given the classification, suggest the right team to handle this.', ... });

const result = await compose(summarizer, classifier, router, {
  transform: (r, i) => i === 0
    ? `Summary:\n${r.text}\n\nPlease classify this document.`
    : r.text,
}).run('CONTRACT-2024-001.pdf contents...');

When to use compose vs graph โ€‹

Use caseUse
Linear, fixed-order pipelinecompose() / pipe()
Conditional branchingpipe(...).then(agent, { when }) or workflow-branching
Cycles, loops, or revisiting stagesGraph workflows
Parallel executionGraph workflows
Durable checkpointing across process restartsGraph workflows
Supervisor / consensus / handoff patternsOrchestration

Where to go next โ€‹

Released under the MIT License.