Skip to content

EN Course 07 Tool Calling

lloydzhou edited this page May 29, 2026 · 1 revision

Tool Calling

Tool calling has three phases:

  1. parse the model tool request
  2. dispatch to a runtime implementation
  3. write the tool result back into the conversation

The dispatch table is intentionally direct:

tool_dispatch() {
    local name="$1"; shift
    case "$name" in
        Read)      tool_read "$@" ;;
        Write)     tool_write "$1" "$2" ;;
        Edit)      tool_edit "$@" ;;
        Bash)      tool_bash "$1" "$2" ;;
        Glob)      tool_glob "$1" "$2" ;;
        Grep)      tool_grep "$1" "$2" "$3" "$4" ;;
        TodoWrite) printf '%s' "$1" ;;
        PlanConfirm) tool_plan_confirm ;;
        PlanClear) tool_plan_clear ;;
        Skill)     tool_skill "$1" ;;
        WebSearch) tool_web_search "$1" ;;
        WebFetch)  tool_web_fetch "$1" ;;
        SubAgent)  tool_sub_agent "$1" "$2" "$3" ;;
    esac
}

Argument Extraction

The model sends JSON. The runtime converts each known tool into positional arguments using a tool-specific parameter list:

tool_param_keys() {
    case "$1" in
        Read) printf 'path offset limit' ;;
        Write) printf 'path content' ;;
        Edit) printf 'path old_string new_string' ;;
        Bash) printf 'command timeout' ;;
        Glob) printf 'pattern path' ;;
        Grep) printf 'pattern path glob context' ;;
    esac
}

This keeps each tool implementation small and avoids re-parsing schema details inside every tool.

Tool Schema as Protocol

tools.json is not just documentation. It is a provider-facing protocol surface shared by all runtimes.

util_load_tool_defs() {
    local tools_file script_dir
    script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    tools_file="$script_dir/tools.json"
    [[ -f "$tools_file" ]] || util_die "Cannot find tools.json: $tools_file"
    TOOL_DEF_JSON=$(<"$tools_file")
}

Claude requests can send this schema directly. OpenAI requests convert the same tool definitions into type=function tools at the transport boundary.

The agent loop should not know which provider shape was used. It only receives normalized TOOL_CALL messages and dispatches by tool name.

Result Formatting

Tool output can be large. The runtime truncates long results before sending them back to the model:

tool_format_result() {
    local output="$1" size marker marker_len tail_lines=5 tail_text tail_len head_len
    if (( ${#output} <= TOOL_RESULT_MAX_BYTES )); then
        printf '%s' "$output"
        return 0
    fi
    # keep the beginning, a truncation marker, and the final lines
}

The key rule is that the assistant tool_use and the corresponding user tool_result must remain paired in conversation history.

Next

Bash Tool Permission Mode explains why the shell tool needs a separate policy layer.

Clone this wiki locally