Inngest AgentKit

repository·main·Indexed 21 days ago

https://github.com/inngest/agent-kit

A toolkit for building AI chat interfaces and agents. It includes @inngest/use-agent, a React hook library for streaming, thread management, and persistence, as well as a History Adapter system (via the HistoryConfig interface) to bridge agent lifecycles with persistence layers like PostgreSQL or MongoDB.

Tokens
100.1K
Snippets
243
Records
353
Agent score
72%

What's inside AgentKit

  1. Overview of the Code Assistant v3 Autonomous Workflow

    main

    Code Assistant v3 is a semi-autonomous AI Agent designed to solve bugs and improve code by navigating a codebase and updating files.

    Unlike previous versions, v3 introduces a Router Agent which provides routing autonomy. This allows the agent to receive a high-level prompt (e.g., a stack trace or error message) and autonomously decide how to navigate the codebase to find and fix the issue.

    Key concepts used in this implementation:

    • Tools: Capabilities provided to the agent to interact with the environment.
    • Agents: Individual units of reasoning.
    • Networks: A collection of agents working together.
    • Router Agent: A specialized agent that manages autonomous routing between other agents in a network.
  2. Voice Assistant Capabilities and Integrations

    main

    The Voice Assistant example demonstrates how AgentKit can orchestrate various tools across different domains:

    macOS Native Integrations

    • Voice Transcription: Uses tools like Superwhisper to convert speech to text.
    • Calendar: View, search, and create calendar events.
    • Reminders & Notes: Manage Apple Reminders and Apple Notes (create, view, search).
    • Communication: Check unread emails, send emails, send iMessages/SMS, and find contacts.

    Web & Third-Party Services

    • Google Maps: Geocoding, reverse geocoding, place search, place details, distance/travel time, and directions.
    • Notion: Create, read, and update Notion pages/documents.
    • Web Search: Uses Exa to perform general knowledge web searches.
  3. What is a Router in AgentKit?

    main

    A Router is a function that acts as the decision-making engine for a Network. It is executed after every agent run to determine the next step in the workflow.

    A router decides whether to:

    1. Call another agent: By returning an instance of an Agent.
    2. Stop execution: By returning undefined.

    Routers have access to the current network state, the stack of agents, the number of iterations performed (callCount), and the result of the most recent agent execution (lastResult).

  4. Handle multiple threads simultaneously

    main

    The useAgent hook processes events for all threads simultaneously in the background. You can monitor background activity by iterating over the threads object.

    To build a multi-thread UI, use the threads object to find threads that are not the currentThreadId and check their hasNewMessages flag to show unread indicators.

    function MultiThreadChat() {
      const { threads, currentThreadId, setCurrentThread } = useAgent({
        threadId: 'primary-thread',
        userId: 'user-123'
      });
    
      const backgroundThreads = Object.entries(threads).filter(
        ([threadId, _]) => threadId !== currentThreadId
      );
    
      const unreadCount = backgroundThreads.reduce(
        (count, [_, threadState]) =>
          count + (threadState.hasNewMessages ? 1 : 0),
        0
      );
    
      return (
        <div>
          <div>Unread: {unreadCount}</div>
          {backgroundThreads.map(([threadId, threadState]) => (
            <div
              key={threadId}
              onClick={() => setCurrentThread(threadId)}
              className={threadState.hasNewMessages ? 'unread' : ''}
            >
              {threadId}: {threadState.messages.length} messages
              {threadState.hasNewMessages && ' 🔴'}
            </div>
          ))}
        </div>
      );
    }
  5. How History Adapters work in AgentKit

    main

    AgentKit uses a History Adapter to bridge the agent's lifecycle with your persistence layer (e.g., PostgreSQL, MongoDB). A History Adapter is a configuration object conforming to the HistoryConfig interface that tells AgentKit how to manage conversation state.

    The HistoryConfig Interface

    MethodPurpose
    createThreadCreates a new conversation thread record in your database.
    getRetrieves a conversation's full message history from your database.
    appendResultsSaves new user and agent messages from the current turn to your database.

    Lifecycle Hooks

    When you call agent.run() or network.run(), AgentKit invokes these methods automatically:

    1. Start of Run: If no threadId exists in the state, AgentKit calls createThread() to generate a new record.
    2. After Initialization: AgentKit calls get() to fetch historical messages and populate the agent's memory. (Note: This is skipped if you provide messages or results directly to createState for client-side optimization).
    3. End of Run: After all work is complete, AgentKit calls appendResults() with only the new messages generated during that specific run to prevent duplicates.
    interface HistoryConfig<T extends StateData> {
      createThread?: (ctx: CreateThreadContext<T>) => Promise<{ threadId: string }>;
      get?: (ctx: Context<T>) => Promise<AgentResult[]>;
      appendResults?: (
        ctx: Context<T> & {
          newResults: AgentResult[];
          userMessage?: { content: string; role: "user"; timestamp: Date };
        }
      ) => Promise<void>;
    }
  6. How AgentKit works: Agents, Networks, Routers, and State

    main

    AgentKit is an orchestration framework for building AI systems ranging from single-model inference to multi-agent systems. The architecture is built on four primary abstractions:

    • Agents: The fundamental unit of work, configured with a name, system prompt, model, and optional tools.
    • Networks: A collection of Agents that work together to solve complex tasks.
    • Router: A component within a Network that determines which Agent should be called next based on the current context.
    • State: The recorded memory of a Network, which can be accessed and used by the Router, Agents, or Tools to collaborate on tasks.

    This orchestration-aware design allows for dynamic, runtime customization of AI workflows.

  7. Core concepts of AgentKit

    main

    AgentKit is designed for building multi-agent networks with deterministic routing and rich tooling. Its core abstractions include:

    • Agents: LLM calls combined with prompts, tools, and MCP (Model Context Protocol).
    • Networks: A mechanism for Agents to collaborate using a shared State (which combines conversation history with a typed state machine) and supporting handoffs.
    • Routers: The orchestration layer that determines autonomy, ranging from code-based logic to LLM-based (e.g., ReAct) orchestration.
    • Tracing: Built-in capabilities to debug and optimize workflows in both local and cloud environments.
  8. How useAgent bridges agents and the UI

    main

    The useAgent hook acts as a bridge between durable agents (running on the backend) and your user interface. Instead of manually managing complex event streams, workflow steps, or token streams, useAgent consumes structured events that describe the agent's lifecycle, content parts, tool calls, and completions. It maintains the UI state for a single conversation or multiple parallel conversations automatically.

    import { useAgent } from "@inngest/use-agent";
    
    export function MyAgentUI() {
      const { messages, sendMessage, status } = useAgent();
    
      const onSubmit = (e) => {
        e.preventDefault();
        const value = new FormData(e.currentTarget).get("input");
        sendMessage(value);
      };
    
      return (
        <div>
          <ul>
            {messages.map(({ id, role, parts }) => (
              <li key={id}>
                <div>{role}</div>
                {parts.map(({ id, type, content }) =>
                  type === "text" ? <div key={id}>{content}</div> : null
                )}
              </li>
            ))}
          </ul>
    
          <form onSubmit={onSubmit}>
            <input name="input" />
            <button type="submit" disabled={status !== "ready"}>
              Send
            </button>
          </form>
        </div>
      );
    }
  9. Understand Agent Execution and Tool Logging

    main

    The voice assistant provides detailed logging to track the agent network execution flow. This includes:

    • Memory Operations: Searching and retrieving relevant memories.
    • Agent Calls: Identification of the active agent (e.g., memory-retriever, personal-assistant, memory-manager).
    • Tool Usage: Detailed lifecycle of tool calls, including:
      • 🔧 Tool Calls: The specific tool being invoked (e.g., get_todays_events).
      • 📥 Tool Inputs: The parameters passed to the tool.
      • ✅ Tool Completion: When the tool finishes execution.
      • 📤 Tool Results: The output/response from the tool.

    Example Log Output:

    🔍 Starting memory retrieval...
    📋 Calling memory-retriever-agent
    🤖 Calling personal-assistant-agent
    💭 Agent is analyzing your request and determining which tools to use...
    🔧 Called tool: get_todays_events
    📥 Input: {}
    ✅ Tool 'get_todays_events' completed
    📤 Result: Found 3 events for today...
    🔧 Called tool: provide_final_answer
    ✅ Personal assistant completed
    💾 Calling memory-manager-agent
    ✅ All agents completed successfully
  10. Core concepts of AgentKit: Agents, Networks, and Routers

    main

    AgentKit is built around three primary abstractions that allow you to scale from simple model calls to complex autonomous systems:

    • Agents: The fundamental building blocks. An Agent is used to call a single model to answer specific questions or perform specific tasks.
    • Networks: Groups of Agents that can work together to achieve more complex, multi-step goals.
    • Routers: Mechanisms used (often in combination with State) to control the flow of execution between different Agents in a network.

    To increase agent capability, you can add Tools to allow agents to act and gather data, or implement reasoning-based routing to dynamically decide which agent should handle a specific request.

  11. How deterministic state-based routing works

    main

    State-based routing models agent workflows as a state machine. Instead of relying on complex prompts for an agent to decide its own next steps, a central router inspects a shared, structured state to determine which agent should run next.

    The workflow loop:

    1. The router inspects the current state.
    2. The router returns an agent (or undefined to terminate).
    3. The agent executes using tools, conversation history, and the current state.
    4. Tools used by the agent modify the shared state.
    5. The loop repeats with the updated state until the router returns undefined.

    This approach makes AI agent systems more predictable, easier to test, and simpler to debug compared to fully autonomous agents.

    // Conceptual loop flow:
    // 1. Router(state) -> Agent
    // 2. Agent(state) -> Tool(modifies state)
    // 3. Router(new_state) -> ...