Executing Your Workflows โก
The moment where everything comes together! Learn how to combine different node types, dependencies, and control flow to create powerful, resilient workflows.
Authentication & Endpoints ๐
Before executing workflows, you'll need to authenticate with Graph Compose:
import { GraphCompose } from '@graph-compose/client'
const client = new GraphCompose({
token: process.env.GRAPH_COMPOSE_TOKEN
});
API Endpoints
All workflow operations are handled through our REST API endpoints (relative to https://api.graphcompose.io/api/v1
):
Endpoint | Method | Description |
---|---|---|
/workflows | POST | Start workflow and return ID immediately (Asynchronous) |
/workflows/execute-sync | POST | Run workflow and wait for completion (Synchronous) |
/workflows/validate | POST | Validate a workflow definition |
/workflows/{id} | GET | Get workflow status and details by ID |
/workflows/{id}/state | GET | Get detailed internal workflow state by ID |
/workflows/{id}/terminate | POST | Request termination of a running workflow |
Anatomy of a Workflow ๐ฌ
Workflow Execution Patterns ๐ฏ
Graph Compose offers two primary ways to execute your workflows via the API and SDK:
๐ก Recommendation: For most use cases, especially workflows involving multiple steps or external calls, asynchronous execution (client.execute()
) is recommended. It provides better resilience against network issues and HTTP timeouts, and is essential for long-running processes. Use synchronous execution (client.executeSync()
) only for very short, quick workflows where you need the result immediately and are confident it will complete within typical request timeouts.
Asynchronous Execution (Recommended)
This is the default and preferred method. You initiate the workflow and receive an ID immediately to check the status later. The SDK's execute()
method uses this pattern, calling the /workflows
endpoint.
// Start execution (recommended)
const { workflowId } = await client.execute({
workflow: {
nodes: [...],
tools: [...] // Optional tools for agent nodes
},
context: { batchSize: 1000 },
webhookUrl: "https://api.example.com/webhook"
});
// Check status later
const status = await client.getStatus(workflowId);
Synchronous Execution
This pattern runs the workflow and waits for completion, returning the final result in the same API call. It's suitable only for very short workflows due to potential HTTP timeouts. The SDK's executeSync()
method uses this pattern, calling the /workflows/execute-sync
endpoint.
import { GraphCompose } from '@graph-compose/client'
// Execute and wait for completion (use with caution for long workflows)
const result = await client.executeSync({
workflow: { nodes: [...] },
context: { userId: "123" }
});
Workflow Responses ๐ฌ
When you retrieve workflow details (e.g., using GET /workflows/{id}
), you'll receive a standardized response. The exact structure is defined in our OpenAPI specification.
The direct response from a synchronous POST /v1/workflows/execute-sync
call may also include the final results directly, potentially differing slightly from the GET
response structure.
Below is an example structure based on the schema:
// Structure based on GET /workflows/{id} response schema
interface WorkflowGetResponse {
success: boolean;
message: string;
data: {
workflow_id: string; // e.g., "clxyzabcd0000uvxyz1234567"
run_id: string; // e.g., "f47ac10b-58cc-4372-a567-0e02b2c3d479"
started_at: string; // e.g., "2023-10-26T10:00:00Z"
user_id: string; // e.g., "auth0|653a3e8a1234567890abcdef"
organization_id: string; // e.g., "org_abcdef1234567890"
status: string; // e.g., "RUNNING", "COMPLETED", etc.
execution_state: { // Detailed internal state
context: Record<string, any>;
executedNodeIds: string[];
nodeResults: Record<string, any>;
httpStatuses: Record<string, { statusCode: number; headers: Record<string, string> } | null >;
};
} | null;
}
// Example usage after fetching
// const response: WorkflowGetResponse = await client.getWorkflow(workflowId);
// if (response.success && response.data) {
// console.log('Workflow Status:', response.data.status);
// console.log('Node Results:', response.data.execution_state.nodeResults);
// }
๐ก Pro tip: For synchronous execution, results are included directly in the response. For async execution, save the workflow_id
and run_id
- you'll need them to query execution status or retrieve results later!
Execution Context ๐ฎ
The execution context is a powerful way to pass data into your workflow. It is available to all nodes via {{context.key}}
:
// Context is available to all nodes via {{context.key}}
const context = {
userId: "123",
environment: "production",
features: ["beta", "dark-mode"]
};
๐ก Pro tip: Start with a simple workflow and iterate. Add complexity (error boundaries, flow control, validation) as needed.
Workflow Structure ๐
When defining a workflow that includes agent nodes and tools, it's important to note the correct placement of different components:
{
"nodes": [
// Nodes go here (HTTP, agent, error boundary nodes)
{
"id": "agent_node",
"type": "agent",
"http": {
// agent configuration
}
}
],
"tools": [
// Tools are defined at the root level, NOT inside nodes
{
"id": "search_tool",
"type": "http",
"http": {
// tool configuration
}
}
]
}
โ ๏ธ Important: Tools are defined at the root level of the workflow definition, not inside the nodes
array. This is because tools are shared resources that can be used by multiple agent nodes in the workflow.
Ready to build something amazing? Let's go!