-
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathautonomous_agent_example.cpp
More file actions
267 lines (220 loc) · 9.26 KB
/
Copy pathautonomous_agent_example.cpp
File metadata and controls
267 lines (220 loc) · 9.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
/**
* @example autonomous_agent_example.cpp
* @brief Autonomous Agent Example
* @version 0.1
* @date 2025-07-20
*
* @copyright Copyright (c) 2026 Edge AI, LLC. All rights reserved.
*
*/
#include <agents-cpp/agents/autonomous_agent.h>
#include <agents-cpp/config_loader.h>
#include <agents-cpp/logger.h>
#include <agents-cpp/tools/tool_registry.h>
#include <chrono>
#include <iostream>
using namespace agents;
// Custom callback to print detailed agent steps
void detailedStepCallback(const AutonomousAgent::Step& step) {
Logger::info("\n=== STEP ===");
Logger::info("Description: {}", step.description);
Logger::info("Status: {}", step.status);
if (step.success) {
Logger::info("\nResult: {}", step.result.dump(2));
} else {
Logger::error("\nFailed!");
}
Logger::info("------------------------------------");
}
// Custom callback for human-in-the-loop
bool detailedHumanApproval(const std::string& message, const JsonObject& context, std::string& modifications) {
if (!context.empty()) {
Logger::info("\nContext Information:");
Logger::info("{}", context.dump(2));
}
Logger::info("🔔 HUMAN APPROVAL REQUIRED 🔔");
Logger::info("{}", message);
Logger::info("Approve this step? (y/n/m - y: approve, n: reject, m: modify): ");
char response;
std::cin >> response;
std::cin.ignore(); // Clear the newline
if (response == 'm' || response == 'M') {
Logger::info("Enter your modifications or instructions: ");
std::string user_modifications;
std::getline(std::cin, user_modifications);
// Set modifications output parameter
modifications = user_modifications;
// Return true to continue with modifications
Logger::info("Continuing with your modifications...");
return true;
}
return (response == 'y' || response == 'Y');
}
int main() {
// Initialize the logger
Logger::init(Logger::Level::INFO);
// Get model choice from user
Logger::info("Select LLM provider (1 for OpenAI, 2 for Anthropic, 3 for Google): ");
int provider_choice;
std::cin >> provider_choice;
std::cin.ignore(); // Clear the newline
// Create LLM based on user choice
std::shared_ptr<LLMInterface> llm;
// Check if we have any API keys configured
auto& config = ConfigLoader::getInstance();
// Proceed based on provider choice and API key in the environment
try {
if (provider_choice == 1) {
llm = createLLM("openai", config.get("OPENAI_API_KEY"), "gpt-4o");
} else if (provider_choice == 2) {
llm = createLLM("anthropic", config.get("ANTHROPIC_API_KEY"), "claude-sonnet-4-5");
} else if (provider_choice == 3) {
llm = createLLM("google", config.get("GEMINI_API_KEY"), "gemini-2.5-flash");
} else {
Logger::error("Invalid provider choice.");
return EXIT_FAILURE;
}
} catch (const std::exception& e) {
Logger::error("Error creating LLM: {}", e.what());
Logger::error("Please ensure the appropriate API key is set in the environment.");
return EXIT_FAILURE;
}
// Configure LLM options
LLMOptions options;
options.temperature = 0.2;
options.max_tokens = 4096;
llm->setOptions(options);
// Create agent context
auto context = std::make_shared<Context>();
context->setLLM(llm);
// Set system prompt for the context
context->setSystemPrompt(
"You are a helpful, autonomous assistant with access to tools. "
"You can use these tools to accomplish tasks for the user. "
"Think step by step and be thorough in your approach."
);
// Register tools from tool registry
auto registry = tools::ToolRegistry::global();
registry.registerStandardTools(llm);
context->registerToolRegistry(registry);
// Create a custom tool
auto summarize_tool = createTool(
"summarize",
"Summarizes a long piece of text into a concise summary",
{
{"text", "The text to summarize", "string", true},
{"max_length", "Maximum length of summary in words", "integer", false}
},
[context](const JsonObject& params) -> ToolResult {
std::string text = params["text"];
int max_length = params.contains("max_length") ? params["max_length"].get<int>() : 100;
// Create a specific context for summarization
auto summary_context = std::make_shared<Context>(*context);
summary_context->setSystemPrompt(
"You are a summarization assistant. Your task is to create concise, accurate summaries "
"that capture the main points of the provided text."
);
std::string prompt = "Summarize the following text in no more than " +
std::to_string(max_length) + " words:\n\n" + text;
LLMResponse llm_response = summary_context->getLLM()->chat(prompt);
std::string summary = llm_response.content;
return ToolResult{
true,
summary,
{{"summary", prompt + "\n\n" + summary}}
};
}
);
context->registerTool(summarize_tool);
// Allow the user to choose planning strategy
Logger::info("Select planning strategy:");
Logger::info("1. ReAct (Open-ended, evolving task)");
Logger::info("2. Plan-and-Execute (Complex, structured task)");
Logger::info("Choice: ");
int strategy_choice;
std::cin >> strategy_choice;
std::cin.ignore(); // Clear the newline
// Create the agent
AutonomousAgent agent(context);
// Set planning strategy based on user choice
AutonomousAgent::PlanningStrategy strategy;
switch (strategy_choice) {
case 1:
strategy = AutonomousAgent::PlanningStrategy::REACT;
break;
case 2:
strategy = AutonomousAgent::PlanningStrategy::PLAN_AND_EXECUTE;
break;
default:
Logger::error("Invalid strategy choice.");
return EXIT_FAILURE;
}
agent.setPlanningStrategy(strategy);
// Set the agent prompt (this extends the context system prompt for the agent)
agent.setAgentPrompt(
"You are an advanced autonomous assistant capable of using tools to help users "
"accomplish their tasks. You break down complex problems into manageable steps "
"and execute them systematically. Always provide clear explanations of your "
"reasoning and approach."
);
// Set up options
AutonomousAgent::Options agent_options;
agent_options.max_iterations = 15;
// Ask user if they want human-in-the-loop mode
Logger::info("Enable human-in-the-loop mode? (y/n): ");
char human_loop_choice;
std::cin >> human_loop_choice;
std::cin.ignore(); // Clear the newline
agent_options.human_feedback_enabled = (human_loop_choice == 'y' || human_loop_choice == 'Y');
if (agent_options.human_feedback_enabled) {
agent_options.human_in_the_loop = detailedHumanApproval;
}
agent.setOptions(agent_options);
// Set up callbacks
agent.setStepCallback(detailedStepCallback);
// Initialize the agent
agent.init();
// Get user input
Logger::info("==================================================");
Logger::info(" AUTONOMOUS AGENT ");
Logger::info("==================================================");
Logger::info("Enter a question or task for the agent (or 'exit' to quit):");
std::string user_input;
while (true) {
Logger::info("\n> ");
std::getline(std::cin, user_input);
if (user_input == "exit" || user_input == "quit" || user_input == "q") {
break;
}
if (user_input.empty()) {
continue;
}
try {
// Start a timer to measure execution time
auto start_time = std::chrono::high_resolution_clock::now();
// Run the agent
JsonObject result = blockingWait(agent.run(user_input));
// End timer
auto end_time = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::seconds>(end_time - start_time).count();
// Display the final result
Logger::info("==================================================");
Logger::info(" FINAL RESULT ");
Logger::info("==================================================");
Logger::info("{}", result["answer"].get<std::string>());
// Display completion statistics
if (result.contains("steps")) {
Logger::info("--------------------------------------------------");
Logger::info("Task completed in {} seconds", duration);
Logger::info("Total steps: {}", result["steps"].get<JsonArray>().size());
}
if (result.contains("tool_calls")) {
Logger::info("Tool calls: {}", result["tool_calls"].get<int>());
}
Logger::info("==================================================");
} catch (const std::exception& e) {
Logger::error("Error: {}", e.what());
}
}
return EXIT_SUCCESS;
}