Tools

July 31, 2026 · View on GitHub

Tools are functions the model can call during a turn (look up memory, run bash, call your API, and so on).

createTenantHome / openAgentSession build a default set. You add or remove tools in code. The runtime does not load tools from an agent/tools/ directory.

Three ways to give the agent powers

ApproachWhen to useHow
Host SessionToolProduct APIs (CRM, billing, your backend)addTools on openSession / run / stream
Sandbox shellFiles, Unix utils, curl, JS/Python, custom bash cmdscreateTenantHome({ sandbox: { … } })
SkillsWritten procedures the model readsagent/skills/ (markdown), not executable code

Prefer a host tool when the work should hit your systems with your auth. Prefer the sandbox when the agent should explore files or run sandboxed code. Skills teach how; they do not register new function calls.

Sandbox details (curl, js-exec, python3, defineCommand): Sandbox.

Default tools

ToolIncluded when
memoryAlways
skills_list, skill_view, skill_manageAlways
session_searchcreateTenantHome (default) or you pass sessionSearchTool
bash, readFile, writeFilecreateTenantHome (default) or you pass sandboxTools

Happy path:

import { createTenantHome } from "@socialrobot-io/agent-kit-node";

const home = await createTenantHome({ tenantId, agent });
const session = await home.openSession(sessionId, {
  addTools: [weather],
  disableTools: ["skill_manage"],
});

Add your own tool

Pass a LanguageModel from any AI SDK provider (or use a Gateway string id with AI_GATEWAY_API_KEY). This example uses in-memory files. For a tenant volume, see Hosting.

import type { SessionTool } from "@socialrobot-io/agent-kit-core";
import { defineAgent, InMemoryFs } from "@socialrobot-io/agent-kit-core";
import { openAgentSession } from "@socialrobot-io/agent-kit-ai";

const tenantId = "brand-123";
const fs = new InMemoryFs();
await fs.writeFile("agent/SOUL.md", "You are a helpful assistant.");
await fs.writeFile("agent/AGENTS.md", "Be brief.");

const session = await openAgentSession({
  tenantId,
  fs,
  definition: defineAgent({ model: "anthropic/claude-sonnet-4-5" }),
});

const weather: SessionTool = {
  name: "weather",
  description: "Short weather summary for a city.",
  inputSchema: {
    type: "object",
    properties: { city: { type: "string" } },
    required: ["city"],
  },
  execute: async (args) => ({
    ok: true,
    city: String(args.city ?? ""),
    summary: "clear",
  }),
};

const turn = await session.run(
  [{ role: "user", content: "Weather in Paris?" }],
  {
    addTools: [weather],
    disableTools: ["skill_manage"],
  },
);
console.log(turn.text);

For streaming chat UIs (useChat), call session.stream with the same override options.

How turn overrides work

OptionEffect
(omit all)Use the default tools for this session
addToolsAdd tools. If a name matches a default, your tool replaces it
disableToolsRemove tools by name
toolsUse only this list. Ignore defaults, addTools, and disableTools

Each SessionTool needs { name, description, inputSchema, execute }.

Search and sandbox without createTenantHome

Prefer createTenantHome (see Hosting). If you wire by hand:

import { createSessionSearchTool, FileTranscriptStore } from "@socialrobot-io/agent-kit-sessions";
import { createTenantBashToolkit } from "@socialrobot-io/agent-kit-sandbox";

const transcripts = new FileTranscriptStore({ fs });
const bash = await createTenantBashToolkit({
  tenantId,
  files: { "README.md": "# workspace\n" },
  destination: "/workspace",
});

const sessionWithExtras = await openAgentSession({
  tenantId,
  fs,
  definition: defineAgent({ model: "anthropic/claude-sonnet-4-5" }),
  sessionSearchTool: createSessionSearchTool(transcripts, tenantId),
  sandboxTools: bash.tools,
});

Prefer addTools on session.run / home.openSession over the older extraTools / extraAiTools names on low-level runAgentTurn.

Next