From cohere-pack
Builds multi-step tool-using agents with Cohere Chat API v2, including TypeScript examples for function definitions, executors, and chat loops.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin cohere-packThis skill is limited to using the following tools:
Build multi-step tool-using agents with Cohere's Chat API v2. The model decides which tools to call, you execute them, and feed results back in a loop until the task is complete.
Implements Claude tool use (function calling) workflows with Anthropic Messages API for AI agents, agent loops, and external system interactions.
Implements layered TypeScript architecture for Cohere API v2 apps with RAG pipelines, agents, embeddings, reranking, and API routes.
Builds LangChain agents with Zod-schema tools, createToolCallingAgent, AgentExecutor, and streaming for autonomous multi-step task execution.
Share bugs, ideas, or general feedback.
Build multi-step tool-using agents with Cohere's Chat API v2. The model decides which tools to call, you execute them, and feed results back in a loop until the task is complete.
cohere-install-auth setupcohere-core-workflow-a (RAG)import { CohereClientV2 } from 'cohere-ai';
const cohere = new CohereClientV2();
// Define tools the model can call
const tools = [
{
type: 'function' as const,
function: {
name: 'get_weather',
description: 'Get current weather for a city',
parameters: {
type: 'object' as const,
properties: {
city: { type: 'string', description: 'City name' },
unit: { type: 'string', enum: ['celsius', 'fahrenheit'], description: 'Temperature unit' },
},
required: ['city'],
},
},
},
{
type: 'function' as const,
function: {
name: 'search_database',
description: 'Search internal database for records',
parameters: {
type: 'object' as const,
properties: {
query: { type: 'string', description: 'Search query' },
limit: { type: 'number', description: 'Max results' },
},
required: ['query'],
},
},
},
];
// Map tool names to actual implementations
const toolExecutors: Record<string, (args: any) => Promise<string>> = {
get_weather: async ({ city, unit = 'celsius' }) => {
// Replace with real weather API call
return JSON.stringify({
city,
temperature: unit === 'celsius' ? 22 : 72,
unit,
condition: 'partly cloudy',
});
},
search_database: async ({ query, limit = 5 }) => {
// Replace with real database query
return JSON.stringify({
results: [
{ id: 1, title: `Result for: ${query}`, relevance: 0.95 },
],
total: 1,
});
},
};
async function singleStepToolUse(userMessage: string) {
// 1. Send message with tools
const response = await cohere.chat({
model: 'command-a-03-2025',
messages: [{ role: 'user', content: userMessage }],
tools,
});
// 2. Check if model wants to call tools
if (response.finishReason === 'TOOL_CALL') {
const toolCalls = response.message?.toolCalls ?? [];
// 3. Execute each tool call
const toolResults = await Promise.all(
toolCalls.map(async (tc) => {
const executor = toolExecutors[tc.function.name];
const args = JSON.parse(tc.function.arguments);
const result = await executor(args);
return {
call: tc,
outputs: [{ result }],
};
})
);
// 4. Send tool results back for final answer
const finalResponse = await cohere.chat({
model: 'command-a-03-2025',
messages: [
{ role: 'user', content: userMessage },
{ role: 'assistant', toolCalls },
{ role: 'tool', toolCallId: toolCalls[0].id, content: toolResults[0].outputs[0].result },
],
tools,
});
return finalResponse.message?.content?.[0]?.text ?? '';
}
// No tool call — direct response
return response.message?.content?.[0]?.text ?? '';
}
async function agentLoop(userMessage: string, maxSteps = 5) {
const messages: any[] = [{ role: 'user', content: userMessage }];
for (let step = 0; step < maxSteps; step++) {
const response = await cohere.chat({
model: 'command-a-03-2025',
messages,
tools,
});
// If model is done (no tool calls), return the answer
if (response.finishReason !== 'TOOL_CALL') {
return response.message?.content?.[0]?.text ?? '';
}
// Model wants to call tools
const toolCalls = response.message?.toolCalls ?? [];
messages.push({ role: 'assistant', toolCalls });
// Execute tools (parallel if multiple)
for (const tc of toolCalls) {
const executor = toolExecutors[tc.function.name];
if (!executor) {
messages.push({ role: 'tool', toolCallId: tc.id, content: `Error: Unknown tool ${tc.function.name}` });
continue;
}
try {
const args = JSON.parse(tc.function.arguments);
const result = await executor(args);
messages.push({ role: 'tool', toolCallId: tc.id, content: result });
} catch (err) {
messages.push({ role: 'tool', toolCallId: tc.id, content: `Error: ${(err as Error).message}` });
}
}
console.log(`Step ${step + 1}: executed ${toolCalls.length} tool(s)`);
}
return 'Agent reached max steps without completing.';
}
// Usage
const answer = await agentLoop("What's the weather in Tokyo and search for 'Tokyo events'?");
console.log(answer);
// Force the model to use at least one tool
const response = await cohere.chat({
model: 'command-a-03-2025',
messages: [{ role: 'user', content: 'Look up the weather in Paris' }],
tools,
toolChoice: 'REQUIRED', // REQUIRED = must use tool, NONE = cannot use tools
});
// toolChoice options:
// - omitted: model decides freely
// - 'REQUIRED': must call at least one tool
// - 'NONE': cannot call any tools (text-only response)
async function streamWithTools(userMessage: string) {
const stream = await cohere.chatStream({
model: 'command-a-03-2025',
messages: [{ role: 'user', content: userMessage }],
tools,
});
const toolCalls: any[] = [];
for await (const event of stream) {
switch (event.type) {
case 'tool-call-start':
console.log(`Tool call: ${event.delta?.message?.toolCalls?.function?.name}`);
break;
case 'tool-call-delta':
// Streaming tool arguments
break;
case 'content-delta':
process.stdout.write(event.delta?.message?.content?.text ?? '');
break;
}
}
}
| Error | Cause | Solution |
|---|---|---|
tool not found | Mismatched tool name | Verify tools array matches executors |
invalid arguments | Schema mismatch | Check tool parameter types |
| Infinite loop | Model keeps calling tools | Set maxSteps limit |
TOOL_CALL with no toolCalls | Edge case | Check response.message?.toolCalls length |
For common errors, see cohere-common-errors.