Agentic AIC++verifiedVerified

Tool Use Agent Pattern in C++

Augment an LLM with callable external tools — APIs, code interpreters, databases — so it can take actions and retrieve real-time information beyond its training data.

How to Implement the Tool Use Agent Pattern in C++

1Step 1: Define tool types and a simple registry

struct ToolResult {
    std::string toolName;
    std::string output;
    bool isError;
};

using ToolHandler = std::function<std::string(const std::map<std::string, std::string>&)>;

class ToolRegistry {
    std::map<std::string, ToolHandler> tools_;
public:
    void registerTool(const std::string& name, ToolHandler handler) {
        tools_[name] = std::move(handler);
    }

    ToolResult execute(const std::string& name,
                       const std::map<std::string, std::string>& params) {
        auto it = tools_.find(name);
        if (it == tools_.end())
            return {name, "Unknown tool: " + name, true};
        try {
            return {name, it->second(params), false};
        } catch (const std::exception& e) {
            return {name, e.what(), true};
        }
    }

    std::vector<std::string> listTools() const {
        std::vector<std::string> names;
        for (const auto& [k, _] : tools_) names.push_back(k);
        return names;
    }
};

2Step 2: Implement the tool-use loop

struct LLMResponse {
    std::string content;
    bool wantsToolCall;
    std::string toolName;
    std::map<std::string, std::string> params;
};

using LLMFn = std::function<LLMResponse(const std::string&, const std::vector<std::string>&)>;

std::string toolUseLoop(const std::string& query,
                        ToolRegistry& registry,
                        LLMFn llm, int maxSteps = 10) {
    std::string context = query;

    for (int i = 0; i < maxSteps; ++i) {
        auto response = llm(context, registry.listTools());
        if (!response.wantsToolCall) return response.content;

        auto result = registry.execute(response.toolName, response.params);
        context += "\nTool(" + result.toolName + "): " + result.output;
    }
    return "Max iterations reached";
}

3Step 3: Demonstrate with a calculator tool

int main() {
    ToolRegistry registry;
    registry.registerTool("add", [](const std::map<std::string, std::string>& p) {
        int a = std::stoi(p.at("a")), b = std::stoi(p.at("b"));
        return std::to_string(a + b);
    });

    auto answer = toolUseLoop(
        "What is 3 + 5?", registry,
        [n = 0](const std::string&, const std::vector<std::string>&) mutable -> LLMResponse {
            if (++n > 1) return {"The answer is 8", false, "", {}};
            return {"", true, "add", {{"a", "3"}, {"b", "5"}}};
        }
    );
    std::cout << answer << "\n";
}

Tool Use Agent Pattern Architecture

hourglass_empty

Rendering diagram...

lightbulb

Tool Use Agent Pattern in the Real World

A lawyer (the LLM) in a courtroom knows the law but needs a paralegal team (the tools) to pull case files, run searches, and retrieve exhibits. The lawyer directs which file to fetch, the paralegal returns it, and the lawyer integrates that information into their argument — the lawyer's intelligence is amplified by the support staff's ability to reach into the real world.