Add subagent mode via agent-as-tool pattern
Each AgentProfile defines a model and a subset of tools. Profiles are registered as callable tools in the main harness so the orchestrator LLM can delegate tasks to specialized subagents. Each invocation runs an isolated Harness with fresh history; only the final answer is returned, keeping the orchestrator context clean. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ add_library(drharness_lib
|
||||
src/ollama_client.cpp
|
||||
src/harness.cpp
|
||||
tools/shell_tool.cpp
|
||||
tools/agent_tool.cpp
|
||||
)
|
||||
target_include_directories(drharness_lib PUBLIC include tools)
|
||||
target_link_libraries(drharness_lib
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct AgentProfile {
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string model;
|
||||
std::vector<std::string> tool_names;
|
||||
};
|
||||
+18
-1
@@ -1,10 +1,24 @@
|
||||
#include "harness.hpp"
|
||||
#include "ollama_client.hpp"
|
||||
#include "tool_registry.hpp"
|
||||
#include "agent_profile.hpp"
|
||||
#include "shell_tool.hpp"
|
||||
#include "agent_tool.hpp"
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
static const std::vector<AgentProfile> profiles = {
|
||||
{
|
||||
.name = "shell_expert",
|
||||
.description = "An agent that can run shell commands to inspect the system, "
|
||||
"files, and processes. Delegate multi-step shell tasks here.",
|
||||
.model = "gemma4:26b",
|
||||
.tool_names = {"run_shell"}
|
||||
},
|
||||
// Add more agent profiles here
|
||||
};
|
||||
|
||||
int main() {
|
||||
OllamaConfig cfg;
|
||||
@@ -13,9 +27,12 @@ int main() {
|
||||
|
||||
ToolRegistry registry;
|
||||
registry.register_tool(make_shell_tool());
|
||||
// Add more tools here:
|
||||
// Add more base tools here:
|
||||
// registry.register_tool(make_file_read_tool());
|
||||
|
||||
for (const auto& profile : profiles)
|
||||
registry.register_tool(make_agent_tool(profile, registry, cfg.base_url));
|
||||
|
||||
Harness harness(OllamaClient(cfg), registry, {.max_tool_iterations = 16, .verbose = true});
|
||||
|
||||
std::cout << "drharness | model: " << cfg.model
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "agent_tool.hpp"
|
||||
#include "harness.hpp"
|
||||
#include "ollama_client.hpp"
|
||||
|
||||
Tool make_agent_tool(const AgentProfile& profile,
|
||||
const ToolRegistry& registry,
|
||||
const std::string& base_url) {
|
||||
return Tool{
|
||||
.name = "agent_" + profile.name,
|
||||
.description = profile.description,
|
||||
.parameters_schema = {
|
||||
{"type", "object"},
|
||||
{"properties", {
|
||||
{"task", {
|
||||
{"type", "string"},
|
||||
{"description", "The task to assign to this agent."}
|
||||
}}
|
||||
}},
|
||||
{"required", {"task"}}
|
||||
},
|
||||
.execute = [profile, ®istry, base_url](const nlohmann::json& args) -> std::string {
|
||||
if (!args.contains("task") || !args["task"].is_string())
|
||||
return "Error: missing required parameter 'task'";
|
||||
|
||||
ToolRegistry sub_registry;
|
||||
for (const auto& tool_name : profile.tool_names) {
|
||||
auto found = registry.find(tool_name);
|
||||
if (found)
|
||||
sub_registry.register_tool(**found);
|
||||
}
|
||||
|
||||
OllamaClient client(OllamaConfig{
|
||||
.base_url = base_url,
|
||||
.model = profile.model,
|
||||
.timeout_s = 120
|
||||
});
|
||||
|
||||
Harness harness(std::move(client), sub_registry, {
|
||||
.max_tool_iterations = 16,
|
||||
.verbose = false
|
||||
});
|
||||
|
||||
try {
|
||||
return harness.chat(args["task"].get<std::string>());
|
||||
} catch (const std::exception& e) {
|
||||
return std::string("Agent error: ") + e.what();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "agent_profile.hpp"
|
||||
#include "tool.hpp"
|
||||
#include "tool_registry.hpp"
|
||||
#include <string>
|
||||
|
||||
Tool make_agent_tool(const AgentProfile& profile,
|
||||
const ToolRegistry& registry,
|
||||
const std::string& base_url);
|
||||
Reference in New Issue
Block a user