Tool
A Tool is a callable an agent can invoke: an HTTP endpoint, a function on an MCP server, another agent or team, or a built-in. For a task-oriented walkthrough see User Guide → Tools and MCP servers; this page is the field-by-field reference.
Spec
Every Tool has a type, an optional description and inputSchema, and exactly one type-specific block matching the type. A complete example (HTTP):
apiVersion: ark.mckinsey.com/v1alpha1
kind: Tool
metadata:
name: example-tool
spec:
# Required: one of http | mcp | agent | team | builtin
type: http
# Description the LLM reads to decide when to call the tool
description: "What this tool does"
# JSON Schema describing the arguments the LLM must supply
inputSchema:
type: object
properties:
city:
type: string
required: ["city"]
# Optional MCP-style hints
annotations:
readOnlyHint: true
title: "Get coordinates"
# The type-specific block (http here). For other types use mcp / agent /
# team / builtin instead — see the sections below.
http:
url: https://geocoding-api.open-meteo.com/v1/search?name={city}&count=1
method: GET
timeout: 30sThe type-specific block must match type: http → spec.http, mcp → spec.mcp, agent → spec.agent, team → spec.team, builtin → spec.builtin. Each is documented below.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
spec.type | enum (http, mcp, agent, team, builtin) | yes | Which kind of tool this is. Drives which type-specific block is required. |
spec.description | string | no | Shown to the LLM as the tool description. Drives whether the model calls it. |
spec.inputSchema | JSON Schema | no | Schema for the arguments the LLM supplies. Validated as JSON Schema by the admission webhook. |
spec.annotations | object | no | MCP-style hints: readOnlyHint, destructiveHint, idempotentHint, openWorldHint, title. |
spec.http | object | for http | HTTP request config (see HTTP tools). |
spec.mcp | object | for mcp | Reference to a function on an MCP server (mcpServerRef + toolName). |
spec.agent | object | for agent | { name } of the Agent to wrap. |
spec.team | object | for team | { name } of the Team to wrap. |
spec.builtin | object | for builtin | { name } — must be terminate or noop. |
status.state is Ready with message Tool configuration is valid when the tool is usable.
The Tool CRD defines no custom print columns, so kubectl get tools shows only Name and Age; use kubectl describe tool <name> or -o yaml to see status.state.
HTTP tools
HTTP API calls with two distinct templating syntaxes:
- URL parameters — single braces
{name}, substituted from the tool-call arguments and URL-encoded. - Body templates — Go template syntax:
{{.input.fieldName}}for arguments,{{.paramName}}forbodyParameters.
GET
apiVersion: ark.mckinsey.com/v1alpha1
kind: Tool
metadata:
name: get-coordinates
spec:
type: http
description: "Returns coordinates for the given city name"
inputSchema:
type: object
properties:
city:
type: string
description: City name to get coordinates for
required: ["city"]
http:
url: https://geocoding-api.open-meteo.com/v1/search?name={city}&count=1
method: GET
timeout: 30sPOST with body template
apiVersion: ark.mckinsey.com/v1alpha1
kind: Tool
metadata:
name: create-user
spec:
type: http
description: "Creates a new user"
inputSchema:
type: object
properties:
name: { type: string }
email: { type: string }
required: ["name", "email"]
http:
url: https://api.example.com/users
method: POST
headers:
- name: Content-Type
value:
value: application/json
body: |
{
"name": "{{.input.name}}",
"email": "{{.input.email}}",
"created_at": "{{.timestamp}}",
"organization": "{{.default_org}}"
}
bodyParameters:
- name: timestamp
value: "2024-01-01T00:00:00Z"
- name: default_org
valueFrom:
configMapKeyRef:
name: user-config
key: default-organization
timeout: 30shttp fields
| Field | Required | Description |
|---|---|---|
url | yes | Endpoint. Must match ^https?://.*. URL {param} placeholders are filled from the tool-call arguments. |
method | no | GET (default), POST, PUT, DELETE, PATCH (also HEAD/OPTIONS). |
headers[] | no | List of { name, value }. Each value is either an inline value, or a valueFrom with a configMapKeyRef or secretKeyRef. |
timeout | no | Per-request timeout, e.g. 30s. |
body | no | Go-template body for POST/PUT/PATCH. {{.input.x}} = arguments; {{.name}} = bodyParameters. |
bodyParameters[] | no | Values for the body template: inline value, or valueFrom (configMapKeyRef / secretKeyRef). |
MCP tools
Tools provided by a Model Context Protocol server. These are normally auto-created by the MCP server controller — when you apply an MCPServer, Ark discovers the functions it advertises and creates one Tool per function, named <mcp-server>-<tool> and labelled mcp/server: <server>. You rarely write these by hand. The generated shape:
apiVersion: ark.mckinsey.com/v1alpha1
kind: Tool
metadata:
name: filesys-server-read-file
labels:
mcp/server: filesys-server
spec:
type: mcp
description: "Read contents of a file"
inputSchema:
type: object
properties:
path: { type: string }
required: ["path"]
mcp:
mcpServerRef:
name: filesys-server
namespace: default
toolName: read_fileAgent and team tools
Wrap an Agent or Team so another agent can call it as a tool. Invoked with a single input argument.
apiVersion: ark.mckinsey.com/v1alpha1
kind: Tool
metadata:
name: call-research-agent
spec:
type: agent
description: "Delegate a research question to the research agent"
inputSchema:
type: object
properties:
input: { type: string }
required: ["input"]
agent:
name: research-agent
---
apiVersion: ark.mckinsey.com/v1alpha1
kind: Tool
metadata:
name: research-team-tool
spec:
type: team
description: "Hand a topic to the research team"
inputSchema:
type: object
properties:
input: { type: string }
required: ["input"]
team:
name: research-teamBuilt-in tools
System functions implemented inside Ark. The ark-tenant chart seeds them as Tool resources, so on a standard install they already exist and you reference them by name. The set of built-ins is fixed in Ark’s code — terminate and noop. The seeded shape:
apiVersion: ark.mckinsey.com/v1alpha1
kind: Tool
metadata:
name: terminate
spec:
type: builtin
description: "Terminates the conversation"
inputSchema:
type: object
properties:
response:
type: string
description: The response to send before terminating
required: ["response"]
builtin:
name: terminate| Built-in | Behaviour |
|---|---|
terminate | Ends the conversation / team turn with a final response. |
noop | Does nothing and returns success — useful for testing and debugging. |
Referencing tools from an agent
Agents reference tools in spec.tools, each with a type matching the Tool’s type and the Tool’s name:
tools:
- type: http
name: get-coordinates
- type: mcp
name: filesys-server-read-file
- type: agent
name: call-research-agent
- type: team
name: research-team-tool
- type: builtin
name: terminate
type: customis deprecated. Use the explicit tool type instead — the mutating webhook stamps a migration warning on agents that still use it.
Partial tools
partial pre-configures some of a tool’s parameters at the agent level and hides them from the LLM, exposing only the rest. partial.name is the real Tool CRD; the outer name/description are what the agent sees.
tools:
- type: http
name: weather-forecast # name exposed to the agent
description: "Get the latest weather forecast"
partial:
name: weather-api # the real Tool CRD (type: http)
parameters:
- name: city
value: "{{ .Query.city }}" # sourced from a query parameter
- name: units
value: "metric" # pinned static valueValidation
Enforced by ark/internal/validation/tool.go:
inputSchema, if set, must be valid JSON Schema.type: httprequireshttp.url; the method (if set) must be a valid HTTP verb.type: mcprequiresmcp.mcpServerRefandmcp.toolName.type: agentrequiresagent.name;type: teamrequiresteam.name.type: builtinrequires the resource name to be a supported built-in (terminate,noop).
Related
- User Guide → Tools and MCP servers — task-oriented walkthrough.
- Reference → MCPServer — registering MCP servers.
- Agents —
spec.toolsand partial-tool injection.