Tools

Built in

Tool
read, write, editfiles, scoped to the workspace
glob, grepfind files and search contents
bashshell, sandboxed, destructive commands always confirm
todothe agent's task list for multi-step work
skillload a procedure on demand
web_searchfive providers: duckduckgo, brave, tavily, serper, searxng
ssh, ssh_connectremote execution, off by default
k8s_get, k8s_apply, k8s_loginKubernetes, read-only by default

Adding your own

Four routes, none of which needs a rebuild. Pick by where your tool already lives.

RouteUse it whenGuide
MCP serverthe tool exists, or you want the industry-standard interfaceMCP
Extensionyou want a tool in any language, with no protocol to learnExtensions
Skillit is a procedure, not a programSkills
SDKyou are embedding Abhed and can write GoSDK

The shortest path

An extension declares its tools once and answers when they are called. Any language; this one is a shell script:

#!/bin/bash
while IFS= read -r line; do
  case "$line" in
    *'"event":"list_tools"'*)
      echo '{"tools":[{"name":"ticket","description":"Look up a ticket by id",
             "schema":{"type":"object","properties":{"id":{"type":"string"}}},
             "mutates":false}]}' ;;
    *'"event":"invoke_tool"'*)
      id=$(jq -r '.args.id' <<<"$line")
      echo "{\"result\": \"$(fetch-ticket "$id")\"}" ;;
    *) echo '{}' ;;
  esac
done
"extensions": [
  { "name": "tickets", "command": "bash", "args": ["/opt/abhed/tickets.sh"] }
]

What a provided tool is, and is not

A tool you add is a tool like any other: it appears in the model's list, its call goes through the policy engine, and its call and result are recorded as events. Adding a tool adds a capability, never a way around the rules — a deny rule naming it still wins, and one that mutates is subject to approval exactly as write is.

Two defaults are deliberately strict:

Writing a description the model will act on

The description is the only thing the model sees before deciding to call something, and it is where most tool integrations fail. Say when to use it, not what it is:

❌ "Ticket lookup API client." ✅ "Look up a ticket by id when the user names one, or when a commit message references one and its details would change what you do."

A vague description produces a tool that is never called, or called for everything.