> ## Documentation Index
> Fetch the complete documentation index at: https://icepick.hatchet.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Parallelization

> Execute independent tasks simultaneously to improve speed and specialized processing

export const CallGraphSequence = props => {
  const actors = [{
    name: 'User',
    left: 20
  }, {
    name: 'Your API',
    left: 160
  }, {
    name: 'Agent',
    left: 300
  }, {
    name: 'Tool',
    left: 440
  }, {
    name: 'Business Logic',
    left: 580
  }];
  const messages = [{
    from: 0,
    to: 1,
    label: 'API Request',
    top: 90,
    dashed: false
  }, {
    from: 1,
    to: 2,
    label: 'agent.run()',
    top: 125,
    dashed: false,
    link: '/api-reference/agent'
  }, {
    from: 2,
    to: 3,
    label: 'tool.run()',
    top: 160,
    dashed: false,
    link: '/api-reference/tool'
  }, {
    from: 3,
    to: 4,
    label: 'External Call',
    top: 195,
    dashed: false
  }, {
    from: 4,
    to: 3,
    label: 'Response',
    top: 230,
    dashed: true
  }, {
    from: 3,
    to: 2,
    label: 'Tool Result',
    top: 265,
    dashed: true
  }, {
    from: 2,
    to: 1,
    label: 'Agent Response',
    top: 300,
    dashed: true
  }, {
    from: 1,
    to: 0,
    label: 'API Response',
    top: 335,
    dashed: true
  }];
  const actorData = props && props.actors ? props.actors : actors;
  const messageData = props && props.messages ? props.messages : messages;
  const height = props && props.height ? props.height : 370;
  const config = {
    actorTop: 30,
    actorWidth: 80,
    lifelineTop: 60,
    lifelineHeight: height,
    lifelineOffset: 40,
    messageSpacing: 140
  };
  return <div className="call-graph-container">
<div className="call-graph-canvas" style={{
    height: height + 30
  }}>
{actorData.map((actor, index) => <div key={index} className="call-graph-actor" style={{
    top: config.actorTop,
    left: actor.left,
    width: config.actorWidth
  }}>
{actor.name}
</div>)}

        {actorData.map((actor, index) => <div key={index} className="call-graph-lifeline" style={{
    top: config.lifelineTop,
    left: actor.left + config.lifelineOffset,
    height: config.lifelineHeight
  }}></div>)}

        {messageData.map((message, index) => {
    const fromActor = actorData[message.from];
    const toActor = actorData[message.to];
    const isReturn = message.from > message.to;
    const messageLeft = isReturn ? toActor.left + config.lifelineOffset + 6 : fromActor.left + config.lifelineOffset;
    const messageWidth = isReturn ? fromActor.left + config.lifelineOffset - (toActor.left + config.lifelineOffset + 6) : toActor.left + config.lifelineOffset - (fromActor.left + config.lifelineOffset);
    return <div key={index} className="call-graph-message" style={{
      top: message.top,
      left: messageLeft,
      width: messageWidth
    }}>
              <div className={`call-graph-message-line ${message.dashed ? 'dashed' : ''}`} style={{
      width: '100%'
    }}></div>
              <div className={`call-graph-arrow ${isReturn ? 'return' : ''}`} style={{
      position: 'absolute',
      [isReturn ? 'left' : 'right']: isReturn ? -4 : -3,
      top: -2
    }}></div>
              {message.link ? <a href={message.link} className="call-graph-message-label" style={{
      position: 'absolute',
      top: -12,
      left: '50%',
      transform: 'translateX(-50%)',
      textDecoration: 'none'
    }}>
                  {message.label}
                </a> : <div className="call-graph-message-label" style={{
      position: 'absolute',
      top: -12,
      left: '50%',
      transform: 'translateX(-50%)'
    }}>
                  {message.label}
                </div>}
            </div>;
  })}
      </div>
    </div>;
};

*Based on [Anthropic's "Building Effective Agents"](https://www.anthropic.com/engineering/building-effective-agents) framework.*

Parallelization executes independent tasks simultaneously rather than sequentially, improving both speed and quality through specialized processing. Tasks that don't depend on each other can run concurrently, with results aggregated using various strategies like sectioning different concerns or voting for consensus-based decisions.

export const parallelizationActors = [{
  name: 'Client',
  left: 20
}, {
  name: 'Agent',
  left: 160
}, {
  name: 'Task A',
  left: 300
}, {
  name: 'Task B',
  left: 440
}];

export const parallelizationMessages = [{
  from: 0,
  to: 1,
  label: 'request',
  top: 90,
  dashed: false
}, {
  from: 1,
  to: 2,
  label: 'parallel task A',
  top: 130,
  dashed: false
}, {
  from: 1,
  to: 3,
  label: 'parallel task B',
  top: 155,
  dashed: false
}, {
  from: 2,
  to: 1,
  label: 'result A',
  top: 195,
  dashed: true
}, {
  from: 3,
  to: 1,
  label: 'result B',
  top: 220,
  dashed: true
}, {
  from: 1,
  to: 0,
  label: 'aggregated response',
  top: 260,
  dashed: true
}];

<CallGraphSequence actors={parallelizationActors} messages={parallelizationMessages} height={285} />

## When to Use

Use parallelization when you have independent tasks that can run simultaneously, such as content generation with safety checking, or multiple evaluations requiring consensus. It's ideal when specialized processing improves quality and when speed gains from concurrency outweigh coordination overhead. Avoid when tasks have dependencies or when the aggregation complexity exceeds the benefits.

## Implementation

This example demonstrates sectioning parallelization where appropriateness checking and main content generation run simultaneously, combining focused attention on different concerns with improved response time.

### Agent Code

```typescript theme={null}
import { icepick } from "@hatchet-dev/icepick";
import z from "zod";
import { appropriatenessCheckTool } from "@tools/appropriateness.tool";
import { mainContentTool } from "@tools/main-content.tool";

const SectioningAgentInput = z.object({
  message: z.string(),
});

const SectioningAgentOutput = z.object({
  response: z.string(),
  isAppropriate: z.boolean(),
});

export const sectioningAgent = icepick.agent({
  name: "sectioning-agent",
  executionTimeout: "2m",
  inputSchema: SectioningAgentInput,
  outputSchema: SectioningAgentOutput,
  description: "Demonstrates parallel processing with sectioning approach",
  fn: async (input, ctx) => {
    // PARALLEL EXECUTION: Both tasks run simultaneously
    const [{ isAppropriate, reason }, { mainContent }] = await Promise.all([
      appropriatenessCheckTool.run({
        message: input.message,
      }),
      mainContentTool.run({
        message: input.message,
      }),
    ]);

    // AGGREGATION: Combine results based on appropriateness check
    if (!isAppropriate) {
      return {
        response: "I can't help with that request. Please ensure your message is appropriate and respectful.",
        isAppropriate: false,
      };
    }

    return {
      response: mainContent,
      isAppropriate: true,
    };
  },
});
```

<AccordionGroup>
  <Accordion title="Appropriateness Check Tool: Safety Guardrail">
    ```typescript theme={null}
    import { icepick } from "@hatchet-dev/icepick";
    import z from "zod";
    import { generateObject } from "ai";

    export const appropriatenessCheckTool = icepick.tool({
      name: "appropriateness-check-tool",
      description: "Evaluates message appropriateness and safety",
      inputSchema: z.object({
        message: z.string(),
      }),
      outputSchema: z.object({
        isAppropriate: z.boolean(),
        reason: z.string(),
      }),
      fn: async (input) => {
        const result = await generateObject({
          model: icepick.defaultLanguageModel,
          prompt: `Evaluate if the following message is appropriate and safe:

    Criteria:
    - No harmful, offensive, or inappropriate content
    - Doesn't promote dangerous activities
    - Respectful and professional tone

    Message: ${input.message}

    Provide your assessment and reasoning.`,
          schema: z.object({
            isAppropriate: z.boolean(),
            reason: z.string(),
          }),
        });

        return {
          isAppropriate: result.object.isAppropriate,
          reason: result.object.reason,
        };
      },
    });
    ```

    This tool runs in parallel with content generation, providing a safety guardrail without blocking the main processing. Using structured output ensures reliable boolean results for decision-making.
  </Accordion>

  <Accordion title="Main Content Tool: Response Generation">
    ```typescript theme={null}
    import { icepick } from "@hatchet-dev/icepick";
    import z from "zod";
    import { generateText } from "ai";

    export const mainContentTool = icepick.tool({
      name: "main-content-tool",
      description: "Generates detailed, helpful responses",
      inputSchema: z.object({
        message: z.string(),
      }),
      outputSchema: z.object({
        mainContent: z.string(),
      }),
      fn: async (input) => {
        const result = await generateText({
          model: icepick.defaultLanguageModel,
          prompt: `You are a helpful assistant. Provide a detailed and informative response to the user's message. Be thorough, accurate, and directly address their question or request.

    User message: ${input.message}`,
        });

        return {
          mainContent: result.text,
        };
      },
    });
    ```

    This tool focuses solely on generating quality content without concern for safety filtering, allowing it to optimize for helpfulness and detail. The parallel execution means safety checking doesn't slow down content generation.
  </Accordion>
</AccordionGroup>

The pattern uses `Promise.all()` to execute independent tasks simultaneously, then aggregates results based on the appropriateness evaluation. This approach provides both speed benefits and specialized processing, with each tool focusing on its specific concern without coordination overhead.

## Related Patterns

This pattern works well with routing for handling different request types and can be combined with evaluator-optimizer for iterative improvement workflows where multiple evaluators provide parallel feedback.
