Skip to content

ExecutionContext

Defined in: gadgets/types.ts:513

Execution context provided to gadgets during execution.

Contains utilities for cost reporting and LLM access. This parameter is optional for backwards compatibility - existing gadgets without the context parameter continue to work.

// Using reportCost() for manual cost reporting
const apiGadget = createGadget({
description: 'Calls external API',
schema: z.object({ query: z.string() }),
execute: async ({ query }, ctx) => {
const result = await callExternalAPI(query);
ctx.reportCost(0.001); // Report $0.001 cost
return result;
},
});
// Using ctx.llmist for automatic LLM cost tracking
const summarizer = createGadget({
description: 'Summarizes text using LLM',
schema: z.object({ text: z.string() }),
execute: async ({ text }, ctx) => {
// LLM costs are automatically reported!
return ctx.llmist.complete('Summarize: ' + text);
},
});

optional agentConfig: AgentContextConfig

Defined in: gadgets/types.ts:637

Parent agent configuration for subagents to inherit.

Contains the model and settings of the agent that invoked this gadget. Subagent gadgets (like BrowseWeb) can use this to inherit the parent’s model by default, rather than using hardcoded defaults.

This is optional - it will be undefined for:

  • Gadgets executed via CLI gadget run command
  • Direct gadget testing without agent context
execute: async (params, ctx) => {
// Inherit parent model unless explicitly specified
const model = params.model ?? ctx.agentConfig?.model ?? "sonnet";
const agent = new AgentBuilder(new LLMist())
.withModel(model)
.build();
// ...
}

optional depth: number

Defined in: gadgets/types.ts:794

Nesting depth of this gadget execution.

  • 0 = Root level (direct gadget call from main agent)
  • 1 = First-level subagent (gadget called by a gadget)
  • 2+ = Deeper nesting

Useful for:

  • Conditional behavior based on nesting level
  • Logging with appropriate indentation
  • Limiting recursion depth
execute: async (params, ctx) => {
// Prevent infinite recursion
if ((ctx.depth ?? 0) > 3) {
return "Maximum nesting depth reached";
}
// Log with depth-aware indentation
const indent = " ".repeat(ctx.depth ?? 0);
console.log(`${indent}Executing at depth ${ctx.depth}`);
}

optional hostExports: HostExports

Defined in: gadgets/types.ts:824

Host llmist exports for external gadgets.

External gadgets MUST use these instead of importing from ‘llmist’ to ensure they use the same version as the host CLI, enabling proper tree sharing and feature compatibility.

Use the getHostExports(ctx) helper function to access these exports with proper error handling.

import { getHostExports, Gadget, z } from 'llmist';
class BrowseWeb extends Gadget({...}) {
async execute(params, ctx) {
const { AgentBuilder } = getHostExports(ctx);
const agent = new AgentBuilder()
.withParentContext(ctx)
.ask(params.task);
}
}

optional invocationId: string

Defined in: gadgets/types.ts:677

Unique invocation ID for this gadget execution. Used by withParentContext() to identify which parent gadget nested events belong to.


optional llmist: CostReportingLLMist

Defined in: gadgets/types.ts:574

Pre-configured LLMist client that automatically reports LLM costs as gadget costs via the reportCost() callback.

All LLM calls made through this client will have their costs automatically tracked and included in the gadget’s total cost.

This property is optional - it will be undefined if:

  • The gadget is executed via CLI gadget run command
  • The gadget is tested directly without agent context
  • No LLMist client was provided to the executor

Always check for availability before use: ctx.llmist?.complete(...)

execute: async ({ text }, ctx) => {
// Check if llmist is available
if (!ctx.llmist) {
return 'LLM not available in this context';
}
// LLM costs are automatically reported
const summary = await ctx.llmist.complete('Summarize: ' + text, {
model: 'haiku',
});
// Additional manual costs can still be reported
ctx.reportCost(0.0001); // Processing overhead
return summary;
}

optional logger: Logger<ILogObj>

Defined in: gadgets/types.ts:850

Logger instance for structured logging.

External gadgets should use this for logging instead of importing defaultLogger directly. This ensures logs respect the CLI’s configured log level, format, and destination (file/console).

The logger is optional to support standalone gadget execution and testing. Use optional chaining when logging: ctx.logger?.debug(...).

execute: async (params, ctx) => {
ctx.logger?.debug("[MyGadget] Starting operation", { itemId: params.id });
// ... do work ...
ctx.logger?.info("[MyGadget] Completed successfully");
return "done";
}

optional nodeId: string

Defined in: gadgets/types.ts:766

The tree node ID for this gadget execution.

This identifies the current gadget’s node in the execution tree. Use with tree methods to query/aggregate data for this subtree:

  • tree.getSubtreeCost(nodeId) - total cost including nested calls
  • tree.getSubtreeMedia(nodeId) - all media from nested gadgets
  • tree.getSubtreeTokens(nodeId) - token usage breakdown
  • tree.getDescendants(nodeId) - all child nodes

Note: This is distinct from invocationId which identifies the gadget call (used in conversation history). nodeId is the tree node identifier.


optional onSubagentEvent: (event) => void

Defined in: gadgets/types.ts:705

Callback for subagent gadgets to report internal events to the parent.

When provided, subagent gadgets (like BrowseWeb) can use this callback to report their internal LLM calls and gadget executions in real-time. This enables the parent agent to display subagent progress indicators.

Recommended: Use builder.withParentContext(ctx) instead of calling this directly - it handles all the forwarding automatically.

SubagentEvent

void

// In a subagent gadget like BrowseWeb - just ONE LINE needed:
execute: async (params, ctx) => {
const agent = new AgentBuilder(client)
.withModel(model)
.withGadgets(Navigate, Click)
.withParentContext(ctx) // <-- Enables automatic event forwarding!
.ask(task);
for await (const event of agent.run()) {
// Events automatically forwarded - just process normally
}
}

signal: AbortSignal

Defined in: gadgets/types.ts:611

Abort signal for cancellation support.

When a gadget times out, this signal is aborted before the TimeoutException is thrown. Gadgets can use this to clean up resources (close browsers, cancel HTTP requests, etc.) when execution is cancelled.

The signal is always provided (never undefined) to simplify gadget code.

// Check for abort at key checkpoints
execute: async (params, ctx) => {
if (ctx.signal.aborted) return 'Aborted';
await doExpensiveWork();
if (ctx.signal.aborted) return 'Aborted';
return result;
}
// Register cleanup handlers
execute: async (params, ctx) => {
const browser = await chromium.launch();
ctx.signal.addEventListener('abort', () => browser.close(), { once: true });
// ... use browser
}
// Pass to fetch for automatic cancellation
execute: async ({ url }, ctx) => {
const response = await fetch(url, { signal: ctx.signal });
return await response.text();
}

optional subagentConfig: SubagentConfigMap

Defined in: gadgets/types.ts:670

Subagent-specific configuration overrides from CLI config.

Contains per-subagent settings defined in [subagents.Name] or [profile.subagents.Name] sections of cli.toml. Allows users to customize subagent behavior without modifying gadget parameters.

Resolution priority (highest to lowest):

  1. Runtime params (explicit gadget call)
  2. Profile-level subagent config
  3. Global subagent config
  4. Parent model (if “inherit”)
  5. Package defaults
execute: async (params, ctx) => {
const subagentConfig = ctx.subagentConfig?.BrowseWeb ?? {};
const model = params.model
?? subagentConfig.model
?? ctx.agentConfig?.model
?? "sonnet";
const maxIterations = params.maxIterations
?? subagentConfig.maxIterations
?? 15;
// ...
}

optional tree: ExecutionTree

Defined in: gadgets/types.ts:751

The execution tree tracking all LLM calls and gadget executions.

Subagent gadgets can use the tree to:

  • Automatically aggregate costs via tree.getSubtreeCost(nodeId)
  • Collect media outputs via tree.getSubtreeMedia(nodeId)
  • Query token usage via tree.getSubtreeTokens(nodeId)

When using withParentContext(ctx), the subagent shares the parent’s tree, enabling unified cost tracking and progress visibility across all nesting levels.

This is optional - it will be undefined for:

  • Gadgets executed via CLI gadget run command
  • Direct gadget testing without agent context
  • Legacy code that hasn’t adopted the ExecutionTree model
execute: async (params, ctx) => {
// Build subagent with parent context (shares tree)
const agent = new AgentBuilder(client)
.withParentContext(ctx)
.withGadgets(Navigate, Click)
.ask(params.task);
for await (const event of agent.run()) {
// Process events...
}
// After subagent completes, costs are automatically tracked in tree
// No need for manual cost aggregation!
const subtreeCost = ctx.tree?.getSubtreeCost(ctx.nodeId!);
// Media from all nested gadgets also aggregated
const allMedia = ctx.tree?.getSubtreeMedia(ctx.nodeId!);
return { result: "done", media: allMedia };
}

reportCost(amount): void

Defined in: gadgets/types.ts:538

Report a cost incurred during gadget execution.

Costs are accumulated and added to the gadget’s total cost. Can be called multiple times during execution. This is summed with any cost returned from the execute() method and any costs from ctx.llmist calls.

number

Cost in USD (e.g., 0.001 for $0.001)

void

execute: async (params, ctx) => {
await callExternalAPI(params.query);
ctx.reportCost(0.001); // $0.001 per API call
await callAnotherAPI(params.data);
ctx.reportCost(0.002); // Can be called multiple times
return 'done';
// Total cost: $0.003
}