Building Agent Nodes
Agent nodes combine AI capabilities with HTTP workflows, enabling autonomous decision-making and tool usage while maintaining HTTP as the core communication protocol. Each agent requires at least one tool to be useful.
Unlike other frameworks, Graph Compose gives you complete control over your agent implementations. You own and operate all services, including agents, which means you can use any AI model, framework, or infrastructure you prefer. Graph Compose simply provides the orchestration layer and contracts for seamless integration.
Implementing Your Agent Endpoint
Your primary responsibility when using agent nodes is to build and host an HTTP endpoint that adheres to the Graph Compose agent contract. This endpoint contains your agent's core logic (e.g., calling an LLM, making decisions).
Agent Logic Cycle
Your endpoint needs to implement the following logic cycle:
Phase | Description | Details |
---|---|---|
Receive State | Agent gets current state | - iterations : Current iteration count- tool_results : Results from previous tools- node_results : Results from dependencies- allResults : All workflow results so far |
Make Decision | Agent chooses next action | - Use a tool to gather information - Complete task and return results |
Process Results | Handle action outcome | - If tool used: Process results and continue - If complete: Move to next workflow node |
Think of your agent endpoint as a smart worker. Graph Compose sends it the current state, and your endpoint decides whether to use a tool (by telling Graph Compose which tool node to execute next) or complete the task. It keeps doing this until it signals completion or hits the iteration limit.
Request Format
Your agent endpoint receives this data each time:
Request Body Sent to Agent Endpoint (Example)
{
"agentId": "your_agent_node_id",
"iteration": 1, // Current iteration number (starts at 1)
"toolCalls": [ // History of tool calls made *by this agent* in previous iterations
{
// Details of the previous tool call (matches ToolHttpRequestSchema)
"toolId": "search_tool",
"payload": { "query": "previous query" }
}
],
"toolResults": [ // History of results from tools called *by this agent* in previous iterations
{
// Details of the previous tool result (matches ToolResultSchema)
"toolId": "search_tool",
"result": { "data": "..." },
"isSuccess": true,
"httpStatus": { "statusCode": 200, "headers": {} }
}
],
"allResults": { // Current state of the *entire* workflow execution
"context": { // Initial context provided when workflow started
"userId": "user-123"
},
"results": { // Results from all *other* completed nodes/tools in the workflow
"get_user_data": { "name": "Alice" },
"some_other_tool": { "value": 42 }
},
"httpStatuses": { // HTTP status details for completed nodes/tools
"get_user_data": { "statusCode": 200, "headers": {} },
"some_other_tool": { "statusCode": 200, "headers": {} }
}
}
}
Response Format
1. Tool Request Response
Instructs Graph Compose to execute a specific tool node next. If an agent determines that a tool should be called, it should return a tool
action with the tool ID and any configuration.
Agent Response: Use Tool
{
"next_action": {
"type": "tool",
"tool_id": "knowledge_base_search", // Must match a tool ID defined in the workflow
"config": { // Payload sent *to the tool* (merged with tool's base config)
"query": "How to reset password",
"max_results": 3
}
}
}
2. Completion Response
Signals that the agent has finished its task and provides the final result. This will allow the graph schema to continue execution.
Agent Response: Complete Task
{
"next_action": {
"type": "complete",
"final_result": { // The data to be stored as this agent node's result
"answer": "The processed information...",
"confidence": 0.95,
"sources": ["doc-123", "doc-456"]
}
}
}
Configuring the Agent Node in Graph Compose
The specific properties for configuring an Agent Node (like http
settings, tools
, dependencies
, and max_iterations
) are defined in its schema.
Tool configuration and implementation details are covered in depth in the Tools section. The examples below focus on agent configuration.
import { GraphCompose } from "@graph-compose/client";
const workflow = new GraphCompose()
.agent("support_agent")
.post("https://api.example.com/agents/support")
.withBody({
context: "Customer support request",
parameters: {
style: "friendly",
max_length: 500
}
})
.withMaxIterations(8)
.withDependencies(["get_user", "get_history"])
.withTools(["search_kb", "fetch_tickets"])
.end();
Iteration Control
Agents have a maximum number of iterations to prevent infinite loops:
- Default is 5 iterations
- Each tool call counts as one iteration
- Set custom limit with
max_iterations
config - Agent fails if limit reached without completion
{
"id": "research_agent",
"type": "agent",
"http": {
"method": "POST",
"url": "https://api.example.com/agents/research",
"config": {
"max_iterations": 10 // Custom iteration limit
}
},
"tools": ["search", "analyze"]
}
If your agent needs more iterations, increase max_iterations
in the config. But be careful - more iterations mean longer execution times!
Examples
Here are some common agent patterns demonstrated as complete REST API request bodies:
// POST /v1/workflows
// Body:
{
"nodes": [
{
"id": "research_agent",
"type": "agent",
"http": {
"method": "POST",
"url": "https://api.example.com/agents/research", // Your agent endpoint
"config": {
"max_iterations": 5
}
},
"tools": [
"web_search", // Reference to the HTTP tool below
"content_processor" // Reference to the Graph tool below
]
}
// ... potentially other nodes in the workflow
],
"tools": [
{
"id": "web_search", // HTTP Tool Definition
"type": "http",
"description": "Performs a web search for a given query.",
"http": {
"method": "GET",
"url": "https://api.search-provider.com/search"
}
},
{
"id": "content_processor", // Graph Tool Definition
"type": "graph",
"description": "Processes fetched content through multiple steps.",
"graph": {
"nodes": [
{
"id": "summarize",
"type": "http",
"http": {
"method": "POST",
"url": "https://api.summarizer.com/summarize"
}
},
{
"id": "analyze_sentiment",
"type": "http",
"dependencies": ["summarize"],
"http": {
"method": "POST",
"url": "https://api.sentiment.com/analyze"
}
}
]
}
}
]
}