TypeScriptADK-TS

ReadonlyContext

Read-only access to invocation identity and session state — used in instruction providers and monitoring callbacks.

ReadonlyContext is the base context class in ADK-TS. It exposes everything your code needs to observe an invocation — who is running, what session it belongs to, and what the current state contains — without exposing any way to change that state. This makes it safe to pass to instruction providers, analytics hooks, and any other code that should read but never write.

import type { ReadonlyContext } from "@iqai/adk";

Properties

userContent

The original message that triggered this invocation. Undefined for system-initiated operations.

get userContent(): Content | undefined

invocationId

A unique identifier for this invocation, generated at the start of each runner.run() call. Use it to correlate logs and events.

get invocationId(): string

agentName

The name of the agent currently executing within this context.

get agentName(): string

appName

The application name configured in the runner.

get appName(): string

userId

The user ID associated with the current session.

get userId(): string

sessionId

The ID of the current session.

get sessionId(): string

state

A frozen snapshot of the current session state. Because the object is frozen, any attempt to write to it will throw a TypeError at runtime — a safety net that makes instruction providers safe by design.

get state(): Readonly<Record<string, any>>

To write to state, use CallbackContext or ToolContext. Both expose a mutable State object in place of this frozen snapshot.

Instruction providers

The most common use of ReadonlyContext is inside instruction provider functions. ADK-TS calls your function before each LLM request and uses the returned string as the system instruction. The function receives a ReadonlyContext so it can tailor the instructions to the current session without accidentally mutating anything.

This example greets the user by name, falls back gracefully if the name hasn't been set yet, and includes the invocation ID for traceability:

import { LlmAgent } from "@iqai/adk";
import type { ReadonlyContext } from "@iqai/adk";

const agent = new LlmAgent({
  name: "greeter",
  description: "Greets users by name using session state",
  model: "gemini-2.5-flash",
  instruction: (ctx: ReadonlyContext) => {
    const name = ctx.state["user:name"] ?? "there";
    const taskCount = (ctx.state["user:taskCount"] as number) ?? 0;

    return [
      `You are a helpful assistant. The user's name is ${name}.`,
      taskCount > 0
        ? `They have completed ${taskCount} tasks so far.`
        : "This is their first session.",
    ].join(" ");
  },
});

Conditional instructions

Use the context to branch instruction content based on state. Each branch should return a complete, self-contained instruction string:

import type { ReadonlyContext } from "@iqai/adk";

function buildInstruction(ctx: ReadonlyContext): string {
  const role = ctx.state["user:role"] as string | undefined;

  if (role === "admin") {
    return "You are an admin assistant. You may discuss internal configuration and user management.";
  }

  if (role === "premium") {
    return "You are a premium assistant with access to advanced features. Help the user leverage them fully.";
  }

  return "You are a helpful assistant. Answer questions clearly and concisely.";
}

Next steps