Connectors

Connectors are the Extend stage of the harness pipeline — how an agent perceives data and reaches the tools it acts through. They are MCP-native, so every MCP server is already a Kraken connector.

#Overview

An agent is only as capable as what it can perceive and reach. Connectors are the bridge: they feed agents data from databases, APIs, and internal systems, and they expose tools the agent can call to do work. A connector is a plain module in your project — the file name is the identity.

Connectors are MCP-native. Kraken did not invent a proprietary connector protocol; it builds on the Model Context Protocol, the open standard for connecting AI systems to external tools. Every MCP server in the ecosystem is automatically a Kraken connector. The platform’s value is the governance, authentication, and health monitoring layer it adds on top — not the protocol itself.

Note

Because connectors are MCP-native, the protocol is portable: you are never locked in by the way your agents reach their tools. See Open by Default.

#Defining a connector

Author a connector with defineConnector and defineTool from @kraken-ai/platform. The definition declares a displayName, a description, the environment variables it needs at runtime, and a record of tools. The file’s path is its identity — a connector at src/connectors/filesystem.ts is the filesystem connector.

ts
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
import { normalize, resolve } from "node:path";
import { defineConnector, defineTool } from "@kraken-ai/platform";
import * as z from "zod";

const DATA_DIR = resolve(process.env.KRAKEN_DATA_DIR ?? "./data");
await mkdir(DATA_DIR, { recursive: true });

const safePath = (relativePath: string): string => {
  const resolved = resolve(DATA_DIR, normalize(relativePath));
  if (resolved !== DATA_DIR && !resolved.startsWith(`${DATA_DIR}/`)) {
    throw new Error("Path traversal denied");
  }
  return resolved;
};

// File at src/connectors/filesystem.ts → identity = "filesystem"
export default defineConnector({
  displayName: "Filesystem",
  description: "Read and write files in the data directory",
  requiredEnvVars: ["KRAKEN_DATA_DIR"],

  tools: {
    fs_read: defineTool({
      description: "Read a file from the data directory",
      input: z.object({ path: z.string().describe("Relative path within data directory") }),
      handler: async ({ path }: { path: string }) => readFile(safePath(path), "utf-8"),
    }),
    fs_write: defineTool({
      description: "Write content to a file",
      input: z.object({
        path: z.string().describe("Relative path within data directory"),
        content: z.string().describe("File content to write"),
      }),
      annotations: { destructiveHint: true },
      handler: async ({ path, content }: { path: string; content: string }) => {
        const safe = safePath(path);
        await mkdir(resolve(safe, ".."), { recursive: true });
        await writeFile(safe, content, "utf-8");
        return { success: true };
      },
    }),
    fs_list: defineTool({
      description: "List files and directories",
      input: z.object({
        path: z.string().optional().describe("Relative path (defaults to root)"),
      }),
      annotations: { readOnlyHint: true },
      handler: async ({ path }: { path?: string }) => {
        const entries = await readdir(safePath(path ?? "."), { withFileTypes: true });
        return entries.map((e: { name: string; isDirectory: () => boolean }) => ({
          name: e.name,
          type: e.isDirectory() ? "dir" : "file",
        }));
      },
    }),
  },
});

requiredEnvVars declares the environment variables a connector reads at runtime, such as a third-party API key. At provisioning time the platform supplies only the declared keys to the connector, sourced from the agent’s configured environment — undeclared keys are not visible to connector code.

#Tools

A tool is a single callable an agent can invoke. defineTool takes a Zod schema as its input and infers the handler’s argument types from it, giving you end-to-end type safety from schema to handler.

descriptionstringRequired

Human-readable description of what the tool does. Surfaced to the agent so it can decide when to call the tool.

inputZodTypeRequired

A Zod schema describing the tool’s arguments. The handler’s parameter type is inferred from this schema.

annotationsToolAnnotationsOptional

Optional MCP tool hints — readOnlyHint, destructiveHint, idempotentHint, and openWorldHint — that describe the tool’s behavior to the model.

handler(args) => resultRequired

The function that runs when the tool is called. Receives the parsed, typed arguments and returns a string, number, boolean, object, array, MCP content, or null/undefined.

#Resources & prompts

Because connectors are MCP-native, a connector can expose more than tools. Alongside the tools record, defineConnector accepts optional resources and prompts records — the resource and prompt primitives from the Model Context Protocol. Resources expose readable content an agent can pull in as context; prompts expose reusable, parameterized message templates.

Resources and prompts pass through the same governance and health layer as tools — every interaction with a connector is mediated by the platform, regardless of which MCP primitive it uses.

#Using a connector in an agent

Attach a connector to an agent through the connectors array on definePlatformAgent. Import the connector module and pass it in — the agent gains every tool the connector exposes.

ts
import { definePlatformAgent } from "@kraken-ai/platform";
import filesystem from "../connectors/filesystem";
import researchGuidelines from "../skills/research-guidelines";

export default definePlatformAgent({
  model: "google/gemini-3-flash-preview",
  instructions:
    "You are a research agent. Use the filesystem tools to read and analyze files. Follow the research-guidelines skill for methodology.",
  skills: [researchGuidelines],
  connectors: [filesystem],
});

For the full agent definition surface — models, teams, skills, and actions — see Agents.

#Governed access

Connectors are where an agent touches real systems, so every tool call a connector serves passes through the governance gateway before it runs. Policies are evaluated at call time and resolve to one of three outcomes:

  • Allow — the call proceeds and the result is returned to the agent.
  • Deny — the call is blocked. Access is deny-by-default: a tool call only runs when policy explicitly permits it.
  • Escalate — the call is paused for human approval before it can proceed.

Every one of these decisions is recorded in the immutable audit trail. See Governance & Policies for how policies are written and evaluated.

#Next steps

  • Actions — The other side of the harness: structured, typed outputs an agent emits to drive downstream work.
  • Governance & Policies — How allow, deny, and escalate decisions are evaluated for every tool call a connector serves.
  • Connector SDK — Full reference for defineConnector, defineTool, resources, prompts, and required environment variables.