npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@graph-compose/client

v1.0.4

Published

Client SDK for Graph Compose

Readme

@graph-compose/client

A fluent TypeScript client for building declarative, Temporal-orchestrated workflows. Compose HTTP-based microservices or multi-agent AI systems with a simple, type-safe API.

Features

  • HTTP Workflow Orchestration - Chain HTTP services with dependency management
  • Multi-Agent AI Workflows - Build ADK (Agent Development Kit) hierarchies with LLMs, tools, and orchestrators
  • Type-Safe Builder Pattern - Fluent API with full TypeScript support
  • JSONata Templating - Dynamic parameter resolution with {{ }} expressions
  • Automatic Retry & Error Handling - Configure retry policies and error boundaries
  • Built-in Validation - Zod-based schema validation for workflows
  • Temporal Integration - Native support for Temporal workflow execution

Installation

npm install @graph-compose/client
# or
pnpm add @graph-compose/client
# or
yarn add @graph-compose/client

Authentication

The client requires an API token to execute workflows against the GraphCompose API:

// Option 1: Pass token in constructor
const graph = new GraphCompose({
  token: 'your-api-token'
});

// Option 2: Set environment variable
// GRAPH_COMPOSE_TOKEN=your-api-token
const graph = new GraphCompose();

API Endpoint: https://api.graphcompose.io/api/v1

Get your API token from the GraphCompose Dashboard

Quick Start

End-to-End Example

import { GraphCompose } from '@graph-compose/client';

// 1. Build your workflow
const graph = new GraphCompose({
  token: process.env.GRAPH_COMPOSE_TOKEN
});

graph
  .node('fetchData')
    .get('https://api.example.com/data')
    .end()
  .node('processData')
    .post('https://api.example.com/process')
    .withBody({ data: '{{results.fetchData}}' })
    .withDependencies(['fetchData'])
    .end();

// 2. Validate it
const validation = graph.validate();
if (!validation.isValid) {
  throw new Error(`Invalid workflow: ${validation.errors.map(e => e.message).join(', ')}`);
}

// 3. Execute it
const result = await graph.execute({
  context: { userId: '123' }
});

// 4. Poll for completion and get results
if (result.success && result.data) {
  const workflowId = result.data.workflowId;

  // Poll until complete
  let status = 'RUNNING';
  while (status === 'RUNNING') {
    await new Promise(resolve => setTimeout(resolve, 1000));
    const statusResult = await graph.getWorkflowStatus(workflowId);
    if (statusResult.success && statusResult.data) {
      status = statusResult.data.status;
    }
  }

  // Get final results
  const finalResult = await graph.getWorkflowStatus(workflowId);
  if (finalResult.success && finalResult.data?.status === 'COMPLETED') {
    console.log('Results:', finalResult.data.execution_state);
  }
}

Traditional HTTP Workflow

Build a workflow that chains multiple HTTP services:

import { GraphCompose } from '@graph-compose/client';

const graph = new GraphCompose({
  token: 'your-api-token'
});

graph
  .node('fetchUser')
    .get('https://api.example.com/users/{{userId}}')
    .withHeaders({
      'Authorization': 'Bearer {{$secret("api_token")}}'
    })
    .end()
  .node('enrichProfile')
    .post('https://api.example.com/enrich')
    .withBody({
      userId: '{{results.fetchUser.id}}',
      email: '{{results.fetchUser.email}}'
    })
    .withDependencies(['fetchUser'])
    .end();

ADK Multi-Agent Workflow

Build an AI agent workflow with tools and orchestration:

import {
  GraphCompose,
  createLlmAgent,
  createHttpTool
} from '@graph-compose/client';

const graph = new GraphCompose();

graph
  .adk('aiAgent')
    .withWorkflow(builder =>
      builder
        .rootAgent('assistant')
        .agent(createLlmAgent({
          id: 'assistant',
          httpConfig: {
            url: 'https://api.example.com/llm',
            method: 'POST'
          },
          tools: ['searchTool'],
          outputKey: 'assistant_response'
        }))
        .httpTool(createHttpTool({
          id: 'searchTool',
          httpConfig: {
            url: 'https://api.example.com/search',
            method: 'POST',
            body: {
              query: '{{state.user_query}}'
            }
          }
        }))
        .build()
    )
    .withInitialPrompt('Hello! How can I help you today?')
    .withMaxCycles(10)
    .end();

HTTP Workflow Builder

Basic HTTP Methods

const graph = new GraphCompose();

// GET request
graph.node('getUser')
  .get('https://api.example.com/users/123')
  .end();

// POST request
graph.node('createUser')
  .post('https://api.example.com/users')
  .withBody({ name: 'John', email: '[email protected]' })
  .end();

// PUT, PATCH, DELETE
graph.node('updateUser').put('https://api.example.com/users/123').end();
graph.node('patchUser').patch('https://api.example.com/users/123').end();
graph.node('deleteUser').delete('https://api.example.com/users/123').end();

Headers and Authentication

graph.node('secureRequest')
  .post('https://api.example.com/data')
  .withHeaders({
    'Authorization': 'Bearer {{$secret("api_token")}}',
    'X-Request-ID': '{{context.requestId}}',
    'Content-Type': 'application/json'
  })
  .end();

Headers also support JSONata parameter objects for dynamic values:

graph.node('dynamicRequest')
  .post('https://api.example.com/data')
  .withHeaders({
    'Authorization': { jsonataExpression: '"Bearer " & $secret("api_token")' }
  })
  .end();

Dynamic Body

graph.node('processOrder')
  .post('https://api.example.com/orders')
  .withBody({
    orderId: '{{results.createOrder.id}}',
    userId: '{{context.userId}}',
    items: '{{results.fetchCart.items}}',
    total: '{{results.calculateTotal.amount}}'
  })
  .end();

Dependencies and Ordering

// Sequential execution
graph
  .node('step1').get('https://api.example.com/step1').end()
  .node('step2').post('https://api.example.com/step2').withDependencies(['step1']).end()
  .node('step3').post('https://api.example.com/step3').withDependencies(['step2']).end();

// Parallel execution (no dependencies)
graph
  .node('fetchUserData').get('https://api.example.com/users').end()
  .node('fetchOrderData').get('https://api.example.com/orders').end()
  .node('fetchPreferences').get('https://api.example.com/prefs').end();

// Fan-out then fan-in
graph
  .node('fetchData1').get('https://api.example.com/data1').end()
  .node('fetchData2').get('https://api.example.com/data2').end()
  .node('aggregate')
    .post('https://api.example.com/aggregate')
    .withDependencies(['fetchData1', 'fetchData2'])
    .end();

Activity Configuration

Configure Temporal activity behavior:

graph.node('reliableCall')
  .post('https://api.example.com/process')
  .withStartToCloseTimeout('30s')
  .withScheduleToCloseTimeout('5m')
  .withRetries({
    maximumAttempts: 5,
    initialInterval: '1s',
    backoffCoefficient: 2.0,
    maximumInterval: '30s'
  })
  .end();

Input/Output Validation

Validate node inputs and outputs using Zod schemas:

import { z } from 'zod';

graph.node('validateRequest')
  .post('https://api.example.com/process')
  .withBody({ data: '{{context.input}}' })
  .withValidation({
    input: z.object({
      data: z.string().min(1)
    }),
    output: z.object({
      result: z.string(),
      status: z.number()
    })
  })
  .end();

Error Boundaries

Wrap nodes with error handling. Error boundaries protect specified nodes and execute their own HTTP endpoint when an error occurs:

graph
  .node('riskyOperation')
    .post('https://api.example.com/risky')
    .end()
  .errorBoundary('handleError', ['riskyOperation'])
    .post('https://api.example.com/fallback')
    .withBody({ error: '{{results.error}}', nodeId: '{{results.nodeId}}' })
    .end();

Conditional Branching

Use withConditions() for conditional workflow control flow:

graph
  .node('checkStatus')
    .get('https://api.example.com/status')
    .withConditions({
      // Terminate the workflow when a condition is met
      terminateWhen: ['{{results.checkStatus.state = "done"}}'],

      // Continue to specific nodes based on conditions
      continueTo: [
        { to: 'processData', when: '{{results.checkStatus.state = "process"}}' },
        { to: 'reviewData', when: '{{results.checkStatus.state = "review"}}' }
      ],

      // Poll until a condition is met
      pollUntil: ['{{results.checkStatus.ready = true}}']
    })
    .end()
  .node('processData')
    .post('https://api.example.com/process')
    .withDependencies(['checkStatus'])
    .end()
  .node('reviewData')
    .post('https://api.example.com/review')
    .withDependencies(['checkStatus'])
    .end();

ADK Agent Workflows

Agent Types

LLM Agent

The primary agent that interacts with language models:

import { createLlmAgent } from '@graph-compose/client';

createLlmAgent({
  id: 'assistant',
  httpConfig: {
    url: 'https://api.example.com/llm',
    method: 'POST'
  },
  instructions: 'You are a helpful assistant.',
  tools: ['searchTool', 'calculatorTool'],
  outputKey: 'assistant_response',
  activityConfig: {
    startToCloseTimeout: '30s',
    retryPolicy: {
      maximumAttempts: 3
    }
  }
})

Sequential Agent

Executes sub-agents in order:

import { createSequentialAgent, createSubAgentReference } from '@graph-compose/client';

createSequentialAgent({
  id: 'pipeline',
  subAgents: [
    createSubAgentReference('extractor'),
    createSubAgentReference('transformer'),
    createSubAgentReference('loader')
  ],
  outputKey: 'pipeline_result'
})

Note: SequentialAgent runs natively in the workflow (not as an HTTP activity).

Parallel Agent

Executes sub-agents concurrently:

import { createParallelAgent, createSubAgentReference } from '@graph-compose/client';

createParallelAgent({
  id: 'fanOut',
  subAgents: [
    createSubAgentReference('analyzer1'),
    createSubAgentReference('analyzer2'),
    createSubAgentReference('analyzer3')
  ]
})

Note: ParallelAgent does NOT support outputKey. Individual sub-agents should have their own outputKey values. ParallelAgent runs natively in the workflow.

Loop Agent

Repeats sub-agents with iteration limits:

import { createLoopAgent, createSubAgentReference } from '@graph-compose/client';

createLoopAgent({
  id: 'retryLoop',
  subAgents: [
    createSubAgentReference('worker')
  ],
  maxAgentLoopIterations: 5,
  loopExitCondition: '{{state.task_completed = true}}',
  outputKey: 'loop_result'
})

Note: LoopAgent runs natively in the workflow (not as an HTTP activity).

Tools

HTTP Tool

Execute external HTTP services:

import { createHttpTool } from '@graph-compose/client';

createHttpTool({
  id: 'searchTool',
  httpConfig: {
    url: 'https://api.example.com/search',
    method: 'POST',
    body: {
      query: '{{state.user_query}}',
      filters: '{{state.filters}}'
    },
    headers: {
      'Authorization': 'Bearer {{$secret("search_api_key")}}'
    }
  },
  outputKey: 'search_results'
})

Agent Tool

Delegate to another agent (specialist pattern):

import { createAgentTool } from '@graph-compose/client';

createAgentTool({
  id: 'specialistTool',
  targetAgentId: 'specialist',
  skipSummarization: false,
  outputKey: 'specialist_result'
})

Complete ADK Example

import {
  GraphCompose,
  createLlmAgent,
  createHttpTool,
  createAgentTool,
  createSubAgentReference
} from '@graph-compose/client';

const graph = new GraphCompose();

graph
  .adk('aiWorkflow')
    .withWorkflow(builder =>
      builder
        // Set the entry point
        .rootAgent('coordinator')

        // Main coordinator agent
        .agent(createLlmAgent({
          id: 'coordinator',
          httpConfig: {
            url: 'https://api.example.com/llm',
            method: 'POST'
          },
          tools: ['researchTool', 'analysisTool'],
          outputKey: 'coordinator_response'
        }))

        // Research specialist
        .agent(createLlmAgent({
          id: 'researcher',
          httpConfig: {
            url: 'https://api.example.com/llm',
            method: 'POST'
          },
          tools: ['searchTool'],
          outputKey: 'research_results'
        }))

        // Analysis specialist
        .agent(createLlmAgent({
          id: 'analyst',
          httpConfig: {
            url: 'https://api.example.com/llm',
            method: 'POST'
          },
          outputKey: 'analysis_results'
        }))

        // HTTP search tool
        .httpTool(createHttpTool({
          id: 'searchTool',
          httpConfig: {
            url: 'https://api.example.com/search',
            method: 'POST'
          },
          outputKey: 'search_data'
        }))

        // Agent tools for delegation
        .agentTool(createAgentTool({
          id: 'researchTool',
          targetAgentId: 'researcher',
          skipSummarization: false
        }))

        .agentTool(createAgentTool({
          id: 'analysisTool',
          targetAgentId: 'analyst',
          skipSummarization: false
        }))

        // Configure workflow-level settings
        .withMaxCycles(20)

        .build()
    )
    .withInitialPrompt('Research and analyze recent AI trends')
    .withState({
      user_id: 'user_123',
      context: 'technology'
    })
    .end();

Advanced Patterns

Agent Handoff Pattern

Nested sub-agents for dynamic routing:

createLlmAgent({
  id: 'router',
  httpConfig: { url: 'https://api.example.com/llm', method: 'POST' },
  subAgents: [
    createLlmAgent({
      id: 'sales_specialist',
      httpConfig: { url: 'https://api.example.com/llm', method: 'POST' }
    }),
    createLlmAgent({
      id: 'support_specialist',
      httpConfig: { url: 'https://api.example.com/llm', method: 'POST' }
    })
  ]
})

Human-in-the-Loop (HITL)

Agents can request human approval:

// Your agent HTTP service returns:
{
  "content": [{"type": "text", "text": "Requesting approval..."}],
  "hitl_request": {
    "type": "approval",
    "message": "Should I proceed with this action?",
    "options": ["approve", "reject", "modify"]
  }
}

State Management

Access shared state across agents:

graph
  .adk('workflow')
    .withWorkflow(builder =>
      builder
        .rootAgent('processor')
        .agent(createLlmAgent({
          id: 'processor',
          httpConfig: {
            url: 'https://api.example.com/llm',
            method: 'POST',
            body: {
              user_theme: '{{state.user_preferences.theme}}',
              auth_status: '{{state.session_data.authenticated}}'
            }
          },
          outputKey: 'processed_data' // Saved to state.processed_data
        }))
        .build()
    )
    // Seed initial state
    .withState({
      user_preferences: { theme: 'dark' },
      session_data: { authenticated: true }
    })
    .withInitialPrompt('Process user data')
    .end();

Exit Flow Control

Agents can terminate the workflow early:

// Your agent HTTP service returns:
{
  "content": [{"type": "text", "text": "Task completed!"}],
  "exit_flow": true  // Stops workflow execution
}

JSONata Templating

All string fields support JSONata expressions with {{ }} delimiters:

Accessing Results

'{{results.fetchUser.id}}'           // Node result
'{{results.fetchUser.profile.name}}' // Nested property

Accessing Context

'{{context.userId}}'       // Workflow context
'{{context.tenantId}}'     // Any context value

Accessing State (ADK)

'{{state.user_query}}'              // Session state
'{{state.preferences.language}}'    // Nested state

Secrets

'{{$secret("api_key")}}'            // Secret reference
'Bearer {{$secret("auth_token")}}'  // In strings

JSONata Operators

// Conditionals
'{{results.status.code = 200 ? "success" : "failure"}}'

// Arithmetic
'{{results.price.amount * 1.1}}'

// String operations
'{{$uppercase(results.user.name)}}'
'{{$substring(results.text, 0, 100)}}'

// Array operations
'{{$count(results.items)}}'
'{{results.items[0].id}}'

Validation

Client-Side Validation

The builder performs comprehensive validation:

const validation = graph.validate();

if (!validation.isValid) {
  validation.errors.forEach(err => {
    console.error(`[${err.name}] ${err.message}`);
  });
}

Validation Checks

  • Node IDs: Unique and valid format (alphanumeric with underscores)
  • Dependencies: Valid references, no circular deps
  • HTTP Config: Valid URLs, methods, headers
  • JSONata: Syntax validation in templates
  • ADK Structure: Agent/tool references, type constraints
  • Schema Compliance: Zod validation against core schemas

Standalone Validation

import { validateWorkflow } from '@graph-compose/client';

const workflow = graph.getWorkflow();
const result = validateWorkflow(workflow);

if (!result.isValid) {
  console.error('Validation failed:', result.errors);
}

Server-Side Validation

Validate against the GraphCompose API (includes tier limits and quota checks):

try {
  const apiResult = await graph.validateApi();

  if (apiResult.success && apiResult.data?.isValid) {
    console.log('Workflow passed server validation');
  } else {
    console.error('Validation failed:', apiResult.data?.errors);
  }
} catch (error) {
  console.error('API error:', error);
}

Endpoint: POST /workflows/validate

Executing Workflows

Async Execution

Start workflow execution and return immediately (recommended for long-running workflows):

const graph = new GraphCompose({ token: 'your-token' });

graph.node('processData')
  .post('https://api.example.com/process')
  .withBody({ data: 'example' })
  .end();

try {
  const result = await graph.execute({
    context: {
      userId: '123',
      requestId: 'req-456'
    },
    webhookUrl: 'https://your-app.com/webhook'  // Optional
  });

  if (result.success && result.data) {
    console.log('Workflow started!');
    console.log('Workflow ID:', result.data.workflowId);
    console.log('Run ID:', result.data.runId);
    console.log('Status:', result.data.status); // "RUNNING"
  }
} catch (error) {
  console.error('Execution failed:', error);
}

Endpoint: POST /workflows

Check Workflow Status

Poll for workflow status after async execution:

const workflowId = 'wf_abc123';

try {
  const statusResult = await graph.getWorkflowStatus(workflowId);

  if (statusResult.success && statusResult.data) {
    console.log('Status:', statusResult.data.status);
    // Possible values: "RUNNING" | "COMPLETED" | "FAILED" | "CANCELLED"
    //                 | "TERMINATED" | "CONTINUED_AS_NEW" | "TIMED_OUT"

    console.log('Started at:', statusResult.data.started_at);

    if (statusResult.data.status === 'COMPLETED') {
      console.log('Results:', statusResult.data.execution_state);
    } else if (statusResult.data.status === 'FAILED') {
      console.log('Error:', statusResult.data.error);
    }
  }
} catch (error) {
  console.error('Failed to get status:', error);
}

Endpoint: GET /workflows/{workflowId}

Terminate Running Workflow

Stop a workflow that's currently executing:

const workflowId = 'wf_abc123';

try {
  const result = await graph.terminateWorkflow(workflowId, {
    runId: 'run_xyz789',  // Optional: specific run ID
    reason: 'User requested cancellation'  // Optional
  });

  if (result.success) {
    console.log('Workflow terminated successfully');
  }
} catch (error) {
  console.error('Failed to terminate:', error);
}

Endpoint: POST /workflows/{workflowId}/terminate

Webhook Notifications

Receive notifications when async workflows complete:

const graph = new GraphCompose({ token: 'your-token' });

graph.node('longProcess')
  .post('https://api.example.com/long-process')
  .end();

graph.withWebhookUrl('https://your-app.com/webhook');

API Response Format

All API methods return a consistent response structure:

interface ApiResponse<T> {
  success: boolean;
  message: string;
  data: T | null;
}

Workflow Status Types

type WorkflowStatus =
  | "RUNNING"          // Workflow is currently executing
  | "COMPLETED"        // Workflow finished successfully
  | "FAILED"           // Workflow encountered an error
  | "CANCELLED"        // Workflow was cancelled
  | "TERMINATED"       // Workflow was manually stopped
  | "CONTINUED_AS_NEW" // Workflow continued as a new execution
  | "TIMED_OUT";       // Workflow exceeded timeout

Complete Execution Example

import { GraphCompose } from '@graph-compose/client';

async function runWorkflow() {
  // Build the workflow
  const graph = new GraphCompose({ token: process.env.GRAPH_COMPOSE_TOKEN });

  graph
    .node('fetchUser')
      .get('https://api.example.com/users/{{context.userId}}')
      .end()
    .node('enrichProfile')
      .post('https://api.example.com/enrich')
      .withBody({
        userId: '{{results.fetchUser.id}}',
        email: '{{results.fetchUser.email}}'
      })
      .withDependencies(['fetchUser'])
      .end();

  // Validate locally
  const validation = graph.validate();
  if (!validation.isValid) {
    throw new Error(`Invalid workflow: ${validation.errors.map(e => e.message).join(', ')}`);
  }

  // Execute async
  const execution = await graph.execute({
    context: { userId: '123' },
    webhookUrl: 'https://myapp.com/webhook'
  });

  if (!execution.success || !execution.data) {
    throw new Error(`Execution failed: ${execution.message}`);
  }

  const workflowId = execution.data.workflowId;
  console.log('Workflow started:', workflowId);

  // Poll for completion
  let status = 'RUNNING';
  while (status === 'RUNNING') {
    await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2s

    const statusResult = await graph.getWorkflowStatus(workflowId);
    if (statusResult.success && statusResult.data) {
      status = statusResult.data.status;
      console.log('Current status:', status);
    }
  }

  // Get final results
  const finalResult = await graph.getWorkflowStatus(workflowId);
  if (finalResult.success && finalResult.data) {
    if (finalResult.data.status === 'COMPLETED') {
      console.log('Workflow completed successfully!');
      console.log('Results:', finalResult.data.execution_state);
    } else {
      console.error('Workflow failed:', finalResult.data.error);
    }
  }
}

runWorkflow().catch(console.error);

API Reference

GraphCompose

Main workflow builder class.

Constructor

new GraphCompose(options?: { token?: string })
  • options.token - API token (or set GRAPH_COMPOSE_TOKEN env var)

Building Methods

  • node(id: string): NodeBuilder - Create HTTP node
  • adk(id: string): AdkNodeBuilder - Create ADK agent node
  • errorBoundary(id: string, protectedNodes: string[]): NodeBuilder - Create error boundary
  • addNode(node: Node): GraphCompose - Add a pre-configured node

Workflow Access Methods

  • getWorkflow(): WorkflowGraph - Get the complete workflow definition
  • toJSON(): WorkflowGraph - Alias for getWorkflow(), suitable for serialization

Configuration Methods

  • withContext(context: Record<string, any>): GraphCompose - Set workflow context
  • withWebhookUrl(url: string): GraphCompose - Set webhook for async notifications
  • withWorkflowConfig(config: WorkflowConfig): GraphCompose - Set workflow-level config

Validation Methods

  • validate(): ClientValidationResult - Client-side validation
  • validateApi(): Promise<ApiResponse> - Server-side validation with tier checks

Execution Methods

  • execute(options?): Promise<ApiResponse> - Execute workflow (returns immediately with workflow ID)
  • getWorkflowStatus(workflowId: string): Promise<ApiResponse> - Check workflow status
  • terminateWorkflow(workflowId: string, options?): Promise<ApiResponse> - Stop workflow

NodeBuilder

Builder for HTTP and error boundary nodes.

HTTP Methods

  • get(url: string) - GET request
  • post(url: string) - POST request
  • put(url: string) - PUT request
  • patch(url: string) - PATCH request
  • delete(url: string) - DELETE request

Configuration

  • withHeaders(headers: Record<string, string | JsonataParam>) - Set headers
  • withBody(body: Record<string, any> | string) - Set request body
  • withRetries(policy: Partial<RetryPolicy>) - Configure retry policy
  • withStartToCloseTimeout(timeout: string) - Set activity timeout
  • withScheduleToCloseTimeout(timeout: string) - Set schedule-to-close timeout
  • withDependencies(nodeIds: string[]) - Set dependencies
  • withConditions(conditions: NodeConditions) - Conditional execution
  • withValidation(config: { input?: ZodType, output?: ZodType }) - Input/output validation

Completion

  • end(): GraphCompose - Finalize node

AdkNodeBuilder

Builder for ADK agent nodes.

Methods

  • withWorkflow(builderFn: (builder: AdkWorkflowBuilder) => ADKWorkflowDefinition) - Define agent workflow via builder callback
  • withInitialPrompt(prompt: string) - Set initial prompt
  • withMaxCycles(max: number) - Set max orchestration cycles
  • withState(state: Record<string, any>) - Seed initial state
  • withDependencies(...deps: string[]) - Set dependencies (variadic)
  • withActivityConfig(config: ActivityConfig) - Set Temporal activity config
  • end(): GraphCompose - Finalize node

AdkWorkflowBuilder

Builder for agent workflow definitions (passed to withWorkflow() callback).

Methods

  • rootAgent(agentId: string) - Set entry point agent
  • agent(config: AgentConfig) - Add agent
  • httpTool(config: GlobalToolDefinition) - Add HTTP tool
  • agentTool(config: GlobalToolDefinition) - Add agent tool
  • withMaxCycles(max: number) - Set workflow-level max cycles
  • build(): ADKWorkflowDefinition - Build the workflow

Helper Functions

Agent Helpers

  • createLlmAgent(config) - Create LLM agent config
  • createSequentialAgent(config) - Create sequential orchestrator
  • createParallelAgent(config) - Create parallel orchestrator
  • createLoopAgent(config) - Create loop orchestrator
  • createSubAgentReference(agentId) - Create agent reference

Tool Helpers

  • createHttpTool(config) - Create HTTP tool config
  • createAgentTool(config) - Create agent tool config

TypeScript Types

Full TypeScript support with exported types. All commonly used types are available directly from the client package:

import type {
  // Core workflow types (re-exported from @graph-compose/core)
  WorkflowGraph,
  HttpNode,
  AdkNode,
  ErrorBoundaryNode,
  Node,
  WorkflowConfig,
  RetryPolicy,
  ActivityConfig,
  NodeConditions,
  ADKWorkflowDefinition,
  AgentConfig,
  GraphWorkflowState,
  GlobalToolDefinition,
  // Client-specific types
  ApiResponse,
  ClientValidationResult,
  ExecuteOptions,
  WorkflowResponse,
  GetWorkflowResponse,
  TerminateWorkflowResponse,
} from '@graph-compose/client';

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.