Plan and Execute
Why use plan mode
The kirha.plan(query, options?) followed by plan.execute(options?) methods to separate planning from execution. Instead of running a query immediately, it returns a plan showing which data providers will be called, what parameters will be used, and the estimated cost. You review the plan, and only then decide to execute it.
This is a human-in-the-loop pattern: the agent proposes a plan, a human (or your application logic) validates it, and execution only happens after explicit approval. This gives you full transparency and control over what data providers are queried and how much each request costs.
Use plan mode when you need to:
- Control costs: review estimated charges before committing to execution
- Human approval: let an operator inspect and approve queries before they run
- Audit trail: log exactly which tools are called with which parameters
- Conditional execution: decide whether to proceed based on the plan contents
Workflow
Create a plan
import { Kirha } from "kirha";
const kirha = new Kirha({
apiKey: process.env.KIRHA_API_KEY,
vertical: "crypto",
});
const plan = await kirha.plan("current portfolio of the largest USDC holder on Base");
console.log(plan.id);
console.log(plan.steps);Each step describes a tool call with its parameters and reasoning:
[
{
id: "step_PGioAXmvzzmxOV0sIoBG8",
toolName: "coingecko_searchCoin",
parameters: {
limit: 1,
query: "USDC",
},
reasoning: "I need to find the CoinGecko ID for USDC to retrieve its contract address on the Base network.",
}
...
]Review the plan
Steps can reference outputs from previous steps using $fromStep and $outputKey, allowing the planner to compose multiple tool calls into a pipeline.
import { Kirha } from "kirha";
const kirha = new Kirha({
apiKey: process.env.KIRHA_API_KEY,
vertical: "crypto",
});
const plan = await kirha.plan("current portfolio of the largest USDC holder on Base");
for (const step of plan.steps) {
console.log(`Tool: ${step.toolName}`);
console.log(`Params: ${JSON.stringify(step.parameters)}`);
console.log(`Reason: ${step.reasoning}`);
} Execute the plan
Once you're satisfied with the plan, call plan.execute() to run it.
import { Kirha } from "kirha";
const kirha = new Kirha({
apiKey: process.env.KIRHA_API_KEY,
vertical: "crypto",
});
const plan = await kirha.plan("current portfolio of the largest USDC holder on Base");
for (const step of plan.steps) {
console.log(`Tool: ${step.toolName}`);
console.log(`Params: ${JSON.stringify(step.parameters)}`);
console.log(`Reason: ${step.reasoning}`);
}
const result = await plan.execute();
console.log(result.data); Plan expiration
Plans expire after 5 minutes. Attempting to execute an expired plan throws a PlanExpiredError. Generate a new plan if this happens.
Handling expired plans
import { Kirha, PlanExpiredError } from "kirha";
const kirha = new Kirha({
apiKey: process.env.KIRHA_API_KEY,
vertical: "crypto",
});
const plan = await kirha.plan("current portfolio of the largest USDC holder on Base");
try {
const result = await plan.execute();
} catch (error) {
if (error instanceof PlanExpiredError) {
// Plan expired, create a new one
const newPlan = await kirha.plan("current portfolio of the largest USDC holder on Base");
const result = await newPlan.execute();
}
}Plan options
Prop
Type
Execute options
Prop
Type
SummarizationConfig
Prop
Type