Structured Tool Results

easy5 mintool-results.ts

Your tools return structured data, documents and long logs, and you want the model to read them well without one huge result filling its context.

What it shows

  • Return json and resource parts with toolContent(), the application keeps the values
  • Cap what the model reads with limits.maxToolResultLength or a tool's maxResultLength, start and end are kept
  • Turn names from data into ones every provider accepts with normalizeToolName()

The code

tool-results.ts
import { Agent, Cogitator, normalizeToolName, tool, toolContent } from '@cogitator-ai/core';
import { z } from 'zod';

const cog = new Cogitator({ limits: { maxToolResultLength: 20_000 } });

const lookupOrder = tool({
  name: normalizeToolName('orders.lookup'),
  description: 'Look up an order by its id',
  parameters: z.object({ id: z.string() }),
  execute: async ({ id }) =>
    toolContent(
      { type: 'json', value: { id, status: 'shipped', carrier: 'DHL' } },
      { type: 'resource', uri: `file:///orders/${id}.md`, mediaType: 'text/markdown', text: 'Fragile, handle with care.' }
    ),
});

const readLog = tool({
  name: 'read_log',
  description: 'Read the full deploy log',
  parameters: z.object({}),
  maxResultLength: 4_000,
  execute: async () => `${'step ok\n'.repeat(10_000)}deploy finished: 3 warnings`,
});

const agent = new Agent({
  name: 'support',
  model: 'ollama/qwen2.5:0.5b',
  instructions: 'Use your tools before you answer.',
  tools: [lookupOrder, readLog],
});

const result = await cog.run(agent, {
  input: 'Who ships order A-17, and how did the last deploy end?',
  onToolResult: (call) => console.log(`${call.name}: the application got the whole result`),
});
console.log(result.output);

await cog.close();

Run it

install · bash
pnpm add @cogitator-ai/core zod
ollama pull qwen2.5:0.5b
run · bash
npx tsx tool-results.ts

Or run the full example from a clone of the repository (keys in .env):

repository · bash
npx tsx examples/core/18-tool-contract.ts

Learn more