Icepick Documentation

repository·main·Indexed 20 days ago

https://github.com/hatchet-dev/icepick

A TypeScript library for building scalable, fault-tolerant AI agents. Icepick leverages Hatchet for durable execution, providing automatic checkpointing and recovery via an event log and replay model. It features a code-first approach to defining Agents, Tools, and Toolboxes, and includes a CLI for project scaffolding and an MCP server for AI-driven agent and tool creation.

Tokens
16.5K
Snippets
57
Records
67
Agent score
63%

What's inside Icepick

  1. How Durable Execution works in Icepick

    main

    Icepick provides durable execution by using a durable task queue (Hatchet). This means every task is stored in a database, allowing agents to recover from failures (like hardware crashes) or wait for long-running external events without consuming resources.

    The Event Log and Replay Model

    When an agent executes, Icepick maintains an event log of all completed steps. If a crash occurs, Icepick automatically replays the execution history to reach the last known successful state.

    Example Workflow:

    1. Start search_documents -> Finish search_documents (Logged)
    2. Start get_document -> Finish get_document (Logged)
    3. Start extract_from_document ... [CRASH OCCURS HERE]

    Recovery Process: Upon restart, Icepick replays the logged events:

    1. Start search_documents (replayed)
    2. Finish search_documents (replayed)
    3. Start get_document (replayed)
    4. Finish get_document (replayed)
    5. Start extract_from_document (replayed) -> Resumes normal execution

    Best Practices for Durable Agents

    To ensure the replay model works correctly, agents must follow these rules:

    • Stateless Reducers: Agents should be stateless and have no side effects. They should not depend on external API calls, database calls, or local disk calls directly within the agent function. Instead, all state should be determined by the results of their tool calls.
    • All work as tasks/tools: Every unit of work should be invoked as a task or a tool call so that it can be captured in the event log.
    • Own your data lookups: Do not allow unconstrained tool calling for data lookups. Tools should validate permissions and separate data lookup from LLM calls for security.
  2. Core Concepts: Agents, Tools, and Toolboxes

    main

    Icepick is built around three primary abstractions:

    • Agents: Functions that represent the high-level logic of an AI agent. They can call other tools or even other agents to complete a task.
    • Tools: Specific functions that perform discrete tasks (e.g., searching a database, calling an API). Tools are the building blocks used by agents.
    • Toolbox: A collection of tools. A toolbox provides AI-powered selection capabilities, allowing an agent to use pickAndRun to dynamically select and execute the most appropriate tool from the collection based on a prompt.
  3. Quickstart with Icepick CLI

    main

    To get started with a new Icepick project, install the CLI globally and use the create command. This will prompt you to select a template to see an end-to-end example of an Icepick agent in action.

    pnpm i -g @hatchet-dev/icepick-cli
    icepick create first-agent
  4. Project structure of the {{name}} agent

    main

    Understanding the directory layout for the {{name}} agent:

    • src/agents/{{kebabCase name}}/: Contains the main agent implementation.
    • src/agents/{{kebabCase name}}/tools/: Contains the tool definitions (weather.ts, time.ts, holiday.ts).
    • src/trigger.ts: The entry point for the interactive CLI.
    • src/main.ts: The entry point for standard execution.
    • src/icepick-client.ts: Configuration for the Icepick client.
    • results/: Directory where results from trigger sessions are saved as markdown files.
  5. Deep Research agent project structure

    main

    The agent implementation is organized as follows:

    • src/agents/deep-research/: Main deep research agent implementation.
    • src/agents/deep-research/tools/: Research tools including:
      • search.tool.ts: Web search using OpenAI's search preview.
      • plan-search.tool.ts: Intelligent search query planning.
      • website-to-md.tool.ts: Converts web pages to markdown.
      • extract-facts.tool.ts: Extracts key facts from sources.
      • judge-facts.tool.ts: Evaluates fact completeness.
      • judge-results.tool.ts: Assesses research quality.
      • summarize.tool.ts: Synthesizes findings into coherent summaries.
    • src/trigger.ts: Interactive CLI for running the agent.
    • src/main.ts: Entry point for standard execution.
    • src/icepick-client.ts: Icepick client configuration.
    • results/: Directory where generated research reports from trigger sessions are stored.
  6. How agents, tools, and toolboxes work together

    main

    Icepick uses a hierarchical registration model to manage AI capabilities:

    1. Agents (icepick.agent) are the primary durable workflows designed to handle complex, long-running tasks with validated I/O.
    2. Tools (icepick.tool) are granular, specialized tasks that perform specific actions.
    3. Toolboxes (icepick.toolbox) group multiple tools into a single logical unit.
    4. Registry & Auto-discovery: When you call .agent(), .tool(), or .toolbox(), they are added to an internal registry. When icepick.start() is called without explicit arguments, it pulls everything from this registry to spin up the worker.
  7. Run {{name}} in development, build, or production modes

    main

    Depending on your workflow, use the following commands:

    • Development Mode: For active coding and testing.
    • Build and Run: To compile the project and run the production-ready version.
    # Development
    pnpm run dev
    
    # Build and Production
    pnpm run build
    pnpm start
    pnpm run dev
    pnpm run build
    pnpm start
  8. Use the Deep Research interactive CLI

    main

    The interactive CLI is the primary way to interact with the agent. Running the trigger command launches a menu that allows you to:

    • Enter research queries for comprehensive investigation.
    • View detailed research results, including sources and analysis.
    • Save research results to markdown files with full citations.

    Run the following command to start:

    pnpm run trigger
  9. Create and register a Toolbox

    main

    A Toolbox is a runtime helper that exposes a collection of Hatchet workflows as tools that a language model can automatically select and execute.

    To use a Toolbox:

    1. Instantiate it with an array of ToolDeclarations and an Icepick client.
    2. Register it with Hatchet using the register property. This registers both your tools and an internal pick-tool workflow required for selection.
    import { Toolbox } from "@hatchet-dev/icepick";
    
    const toolbox = new Toolbox({ tools: [myTool, otherTool] }, icepickClient);
    
    // Register the toolbox and its internal workflows with Hatchet
    await icepickClient.register(toolbox.register);
    const toolbox = new Toolbox({ tools: [myTool, otherTool] }, icepickClient);
    await icepickClient.register(toolbox.register);
  10. Define and implement an Icepick agent

    main

    An Icepick agent is defined using icepick.agent(). It requires a unique name, an inputSchema and outputSchema (typically defined using zod), a description, and an asynchronous fn function that contains the agent's logic.

    Inside the fn function, agents typically use a toolbox to execute tools. The toolbox.pickAndRun() method is used to process a prompt and select/execute the appropriate tool. The result of pickAndRun should be handled via a switch statement on result.name, or by using toolbox.assertExhaustive(result) to ensure all possible tool outcomes are covered.

    import { icepick } from "@/icepick-client";
    import z from "zod";
    
    const MyAgentInput = z.object({
      message: z.string(),
    });
    
    const MyAgentOutput = z.object({
      message: z.string(),
    });
    
    export const myToolbox = icepick.toolbox({
      tools: [
        // tools go here
      ],
    });
    
    export const myAgent = icepick.agent({
      name: "my-agent",
      executionTimeout: "1m",
      inputSchema: MyAgentInput,
      outputSchema: MyAgentOutput,
      description: "A description of what the agent does",
      fn: async (input, ctx) => {
        const result = await myToolbox.pickAndRun({
          prompt: input.message,
        });
    
        switch (result.name) {
          case "someTool":
            return { message: `Result: ${result.output}` };
          default:
            return myToolbox.assertExhaustive(result);
        }
      },
    });
  11. Initialize the Icepick client

    main

    To use Icepick, initialize the Icepick class using Icepick.init() or the constructor. You must provide a defaultLanguageModel (from the ai package) in the ClientConfig.

    Icepick extends Hatchet, so it accepts standard HatchetClientOptions and AxiosRequestConfig for network configuration.

    import Icepick from '@hatchet-dev/icepick';
    import { openai } from '@ai-sdk/openai'; // Example provider
    
    const icepick = Icepick.init({
      defaultLanguageModel: openai('gpt-4o'),
    }, {
      // Hatchet client options
    });