Tool Execution Patterns
How tools are executed matters as much as what they do. CoFounder supports sequential execution, parallel execution, chaining, and conditional patterns. Choosing the right pattern can dramatically improve agent speed and reliability.
Sequential Execution
Sequential execution is the default. The agent calls one tool at a time, waits for the result, and then decides its next action. This is the safest pattern and works well when each step depends on the previous result.
import { createAgent } from '@waymakerai/aicofounder-core';
const agent = createAgent({
name: 'sequential-agent',
model: 'gpt-4o',
systemPrompt: `You are a research assistant. When asked a question:
1. First search for relevant information
2. Then fetch the most relevant page
3. Finally summarize the findings`,
tools: [searchTool, fetchPageTool, summarizeTool],
execution: { mode: 'sequential' }, // default
});Parallel Execution
When an agent needs independent pieces of information, it can call multiple tools simultaneously. CoFounder detects when the LLM requests multiple tool calls in a single response and runs them in parallel using Promise.all:
const agent = createAgent({
name: 'parallel-agent',
model: 'gpt-4o',
systemPrompt: `You are a comparison assistant. When comparing items,
fetch data for ALL items simultaneously using parallel tool calls.`,
tools: [fetchProductTool, fetchReviewsTool, fetchPriceTool],
execution: {
mode: 'parallel',
maxConcurrent: 5, // Limit concurrent tool calls
timeoutMs: 30000, // Timeout per tool call
},
});
// The agent will call fetchProductTool for multiple products at once
const result = await agent.run('Compare the iPhone 15 Pro and Samsung S24 Ultra');Parallel execution can reduce total latency by 50-80% for multi-source queries, but be mindful of rate limits on external APIs.
Tool Chaining
Tool chaining is when the output of one tool becomes the input of another. CoFounder supports explicit chaining through the chainTools helper:
import { chainTools } from '@waymakerai/aicofounder-core';
const searchAndSummarize = chainTools([
{
tool: searchTool,
mapOutput: (results) => ({
urls: JSON.parse(results).map((r: any) => r.url).slice(0, 3),
}),
},
{
tool: fetchPageTool,
mapOutput: (pages) => ({
content: JSON.parse(pages).map((p: any) => p.text).join('\n\n'),
}),
},
{
tool: summarizeTool,
},
]);
// Register the chain as a single composite tool
const agent = createAgent({
name: 'chaining-agent',
model: 'gpt-4o',
tools: [searchAndSummarize],
});Conditional Tool Use
Sometimes a tool should only be available based on context. CoFounder allows dynamic tool filtering with the toolFilter option:
- Filter tools based on user permissions or roles
- Enable expensive tools only when simpler ones fail
- Restrict tools based on the current step count
const agent = createAgent({
name: 'conditional-agent',
model: 'gpt-4o',
tools: [quickSearchTool, deepSearchTool, databaseTool],
toolFilter: ({ step, previousResults }) => {
// Only allow deep search after step 3 if quick search was insufficient
if (step < 3) return ['quick_search', 'database'];
return ['quick_search', 'deep_search', 'database'];
},
});Parsing Tool Results
Tool results are always strings (JSON-serialized). CoFounder provides utilities to help agents parse and validate tool output:
- Always return valid JSON from your tools -- agents reason about structured data more reliably.
- Include metadata like timestamps, source URLs, or confidence scores so the agent can assess quality.
- Keep results concise. Large tool outputs consume context window space and can confuse the agent.