Tool Caching
RadarOS supports result caching for tools. When a tool is called with the same arguments within the TTL window, the cached result is returned instantly — no re-execution.
Quick Start
import { Agent , openai , defineTool } from "@radaros/core" ;
import { z } from "zod" ;
const weatherTool = defineTool ({
name: "getWeather" ,
description: "Get current weather for a city" ,
parameters: z . object ({
city: z . string (). describe ( "City name" ),
}),
execute : async ({ city }) => {
const res = await fetch ( `https://api.weather.com/ ${ city } ` );
return await res . text ();
},
cache: { ttl: 60_000 }, // Cache for 1 minute
});
const agent = new Agent ({
name: "WeatherBot" ,
model: openai ( "gpt-4o" ),
tools: [ weatherTool ],
});
If the agent calls getWeather("Mumbai") twice within 60 seconds, the second call returns the cached result without hitting the API.
Configuration
Add a cache property to any tool definition:
Time-to-live in milliseconds. Cached results expire after this duration. Example: 60_000 for 1 minute, 300_000 for 5 minutes.
How It Works
When a tool is called, the ToolExecutor generates a cache key from the tool name and a stable serialization of the arguments.
If a valid (non-expired) cache entry exists for that key, the result is returned immediately.
If no cache entry exists, the tool executes normally and the result is stored with an expiry timestamp.
Tool Call → Cache Lookup
├─ HIT → Return cached result (skip execution)
└─ MISS → Execute tool → Store result → Return
Cache Key Strategy
Cache keys are generated as toolName:stableStringify(args) — arguments are sorted by key to ensure consistent hashing regardless of property order.
// These produce the same cache key:
getWeather ({ city: "Mumbai" , unit: "celsius" })
getWeather ({ unit: "celsius" , city: "Mumbai" })
Clearing the Cache
Tool result caches are scoped to each ToolExecutor instance, which is recreated per request when using toolRouter. For agents without a tool router, the cache persists across runs on the same agent instance.
Cache entries expire automatically based on ttl. To manually clear all cached results, create a fresh agent or call setTools() to rebuild the tool executor.
When to Use
Good Candidates
External API calls (weather, exchange rates)
Database lookups with stable results
Expensive computations
Rate-limited APIs
Poor Candidates
Tools with side effects (send email, write file)
Real-time data that changes every second
Tools where arguments include timestamps
interface ToolCacheConfig {
ttl : number ; // milliseconds
}
Logging
When logLevel is "info" or higher, cached tool results are prefixed with [cached] in the logs, making it easy to verify caching behavior during development.
Cache Behavior Example
When the same tool is called with identical arguments within the TTL window, the cached result is returned instantly without re-executing:
const weatherTool = defineTool ({
name: "getWeather" ,
description: "Get current weather" ,
parameters: z . object ({ city: z . string () }),
execute : async ({ city }) => {
console . log ( `[API CALL] Fetching weather for ${ city } ` );
const data = await weatherAPI . get ( city );
return ` ${ city } : ${ data . temp } °C, ${ data . condition } ` ;
},
cache: { ttl: 60_000 }, // 1 minute
});
const agent = new Agent ({
name: "assistant" ,
model: openai ( "gpt-4o" ),
tools: [ weatherTool ],
});
// First call — executes the tool, logs "[API CALL]"
await agent . run ( "What's the weather in Tokyo?" );
// Second call within 60s — returns cached result, no API call
await agent . run ( "Tell me Tokyo's weather again" );
// After 60s — cache expired, executes again
Each tool can have its own cache duration based on how frequently the data changes:
const tools = [
defineTool ({
name: "getExchangeRate" ,
description: "Get currency exchange rate" ,
parameters: z . object ({ from: z . string (), to: z . string () }),
execute : async ({ from , to }) => { /* ... */ },
cache: { ttl: 300_000 }, // 5 minutes — rates change slowly
}),
defineTool ({
name: "getStockPrice" ,
description: "Get current stock price" ,
parameters: z . object ({ symbol: z . string () }),
execute : async ({ symbol }) => { /* ... */ },
cache: { ttl: 30_000 }, // 30 seconds — prices change fast
}),
defineTool ({
name: "getCurrentTime" ,
description: "Get the current date and time" ,
parameters: z . object ({}),
execute : async () => new Date (). toISOString (),
// No cache — always fresh
}),
];