These C++ examples are real runnable files. Edit the source file first; this page is rebuilt from the checked-in example and its metadata header.
C++ Grounded Support Agent
Answers a support question grounded in a handbook that is kept out of the model prompt via contextFields.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
beginner - Run:
npm run example -- cpp src/examples/cpp/short-agents/basic_agent.cpp - Source: src/examples/cpp/short-agents/basic_agent.cpp
#include "axllm/axllm.hpp"
#include "axllm/runtime/quickjs/quickjs_runtime.hpp"
#include <cstdlib>
#include <iostream>
int main() {
const char* key = std::getenv("OPENAI_API_KEY");
if (key == nullptr || std::string(key).empty()) key = std::getenv("OPENAI_APIKEY");
if (key == nullptr || std::string(key).empty()) {
std::cerr << "Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.\n";
return 2;
}
const char* model = std::getenv("AX_OPENAI_MODEL");
axllm::OpenAICompatibleClient client(axllm::object({
{"api_key", key},
{"model", model == nullptr || std::string(model).empty() ? "gpt-5.4-mini" : model},
{"model_config", axllm::object({{"temperature", 0}})},
}));
// The handbook can be arbitrarily large. Listing it in `contextFields` keeps it
// in the agent's runtime so it never inflates the model prompt -- the agent reads
// it through code, not through tokens. That is the whole point of an Ax agent
// over a plain gen() call: the source material stays out of the context window.
std::string handbook =
"# Acme Cloud -- Support Handbook\n"
"\n"
"## Billing\n"
"- Invoices are issued on the 1st of each month and are due net-15.\n"
"- Plan downgrades take effect at the END of the current billing cycle, not immediately.\n"
"- Refunds are issued to the original payment method within 5 business days.\n"
"\n"
"## Access\n"
"- Seats can be added by any workspace Owner under Settings -> Members.\n"
"- SSO (SAML) is available on Enterprise; SCIM provisioning is Owner-only.\n"
"\n"
"## Incidents\n"
"- Status and uptime are published at status.acme.example.\n"
"- Sev-1 incidents page the on-call within 5 minutes; updates post every 30 minutes.\n"
"\n"
"## Data\n"
"- Exports are available in CSV and JSON from Settings -> Data.\n"
"- Deleted workspaces are recoverable for 30 days, then permanently purged.";
auto assistant = axllm::agent(
"question:string, handbook:string -> answer:string, citations:string[] \"Handbook sections the answer relies on\"",
// Keep the handbook in the runtime, out of the prompt.
axllm::object({
{"contextFields", axllm::array({"handbook"})},
{"runtime", axllm::object({{"language", "JavaScript"}})},
}));
axllm::runtime::quickjs::QuickJsCodeRuntime runtime;
axllm::Value result = assistant.forward(
client,
axllm::object({
{"question", "A customer downgraded their plan today. When does it take effect, and can they get a refund for the current cycle?"},
{"handbook", handbook},
}),
axllm::object({{"runtime", axllm::Core::code_runtime_ref(runtime)}, {"max_actor_steps", 12}}));
std::cout << axllm::stringify(result) << "\n";
}C++ Incident Triage Agent
Triages a noisy incident report held in contextFields, using a lean contextPolicy to keep the raw log out of the prompt while it reasons.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
intermediate - Run:
npm run example -- cpp src/examples/cpp/short-agents/tools_agent.cpp - Source: src/examples/cpp/short-agents/tools_agent.cpp
#include "axllm/axllm.hpp"
#include "axllm/runtime/quickjs/quickjs_runtime.hpp"
#include <cstdlib>
#include <iostream>
int main() {
const char* key = std::getenv("OPENAI_API_KEY");
if (key == nullptr || std::string(key).empty()) key = std::getenv("OPENAI_APIKEY");
if (key == nullptr || std::string(key).empty()) {
std::cerr << "Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.\n";
return 2;
}
const char* model = std::getenv("AX_OPENAI_MODEL");
axllm::OpenAICompatibleClient client(axllm::object({
{"api_key", key},
{"model", model == nullptr || std::string(model).empty() ? "gpt-5.4-mini" : model},
{"model_config", axllm::object({{"temperature", 0}})},
}));
// A raw, noisy incident report. It lives in `contextFields`, so the agent works
// it inside the runtime; `contextPolicy: lean` keeps the prompt compact by
// preferring live runtime state and summaries over replaying the raw text.
std::string report =
"[2026-03-02 14:01:22Z] INFO gateway deploy svc-checkout-edge v812 -> prod (channel: canary 10%)\n"
"[2026-03-02 14:03:10Z] WARN checkout-api p95 latency 1180ms (baseline 240ms) region=eu-west-1\n"
"[2026-03-02 14:04:55Z] ERROR checkout-api 502 from svc-payments-gw: upstream timeout (10s) tenant_tier=enterprise\n"
"[2026-03-02 14:05:01Z] ERROR checkout-api 502 from svc-payments-gw: upstream timeout (10s) tenant_tier=enterprise\n"
"[2026-03-02 14:05:40Z] WARN payments-gw circuit half-open, 3 retries exhausted for order=ord_99214\n"
"[2026-03-02 14:06:12Z] INFO gateway canary widened 10% -> 50% for svc-checkout-edge v812\n"
"[2026-03-02 14:07:33Z] ERROR checkout-api 502 from svc-payments-gw: upstream timeout (10s) tenant_tier=enterprise\n"
"[2026-03-02 14:08:02Z] ERROR checkout-api user-visible: \"Payment could not be processed\" shown to 1,284 sessions\n"
"[2026-03-02 14:09:48Z] WARN payments-gw connection pool exhausted (max=64) waiting=210\n"
"[2026-03-02 14:11:20Z] INFO on-call paged: SEV-2 opened (eu-west-1 checkout error rate 38%)\n"
"[2026-03-02 14:14:05Z] INFO gateway rollback svc-checkout-edge v812 -> v811 (channel: prod 100%)\n"
"[2026-03-02 14:17:41Z] INFO checkout-api p95 latency 260ms, error rate 0.4% region=eu-west-1\n"
"[2026-03-02 14:19:10Z] INFO on-call SEV-2 mitigated, monitoring for 30m";
auto triage = axllm::agent(
"report:string, question:string -> severity:class \"low, medium, high, critical\", rootCause:string, nextSteps:string[], evidence:string[] \"Quoted log lines that support the assessment\"",
axllm::object({
{"contextFields", axllm::array({"report"})},
{"contextPolicy", axllm::object({{"preset", "lean"}, {"budget", "balanced"}})},
{"runtime", axllm::object({{"language", "JavaScript"}})},
}));
axllm::runtime::quickjs::QuickJsCodeRuntime runtime;
axllm::Value result = triage.forward(
client,
axllm::object({
{"report", report},
{"question", "What happened, how bad was it, and what should the on-call do next? Cite the lines you relied on."},
}),
axllm::object({{"runtime", axllm::Core::code_runtime_ref(runtime)}, {"max_actor_steps", 12}}));
std::cout << axllm::stringify(result) << "\n";
}C++ Specialist Planner Agent
A specialist that plans a migration from a long brief held in contextFields, using a checkpointed contextPolicy and a runtime-output cap to stay compact.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
advanced - Run:
npm run example -- cpp src/examples/cpp/short-agents/handoff_agent.cpp - Source: src/examples/cpp/short-agents/handoff_agent.cpp
#include "axllm/axllm.hpp"
#include "axllm/runtime/quickjs/quickjs_runtime.hpp"
#include <cstdlib>
#include <iostream>
int main() {
const char* key = std::getenv("OPENAI_API_KEY");
if (key == nullptr || std::string(key).empty()) key = std::getenv("OPENAI_APIKEY");
if (key == nullptr || std::string(key).empty()) {
std::cerr << "Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.\n";
return 2;
}
const char* model = std::getenv("AX_OPENAI_MODEL");
axllm::OpenAICompatibleClient client(axllm::object({
{"api_key", key},
{"model", model == nullptr || std::string(model).empty() ? "gpt-5.4-mini" : model},
{"model_config", axllm::object({{"temperature", 0}})},
}));
// A long, messy brief -- exactly the kind of input you do not want replayed into
// the prompt on every turn. `contextFields` holds it in the runtime, the
// `checkpointed` policy compacts older turns once the prompt grows, and
// `maxRuntimeChars` caps how much runtime output is echoed back.
std::string brief =
"# Migration brief: monolith -> services (draft, unordered notes)\n"
"\n"
"Current: single Rails monolith, Postgres primary + 1 replica, Sidekiq for jobs.\n"
"Pain: deploys take 40m, one bad migration locks the orders table, on-call burnout.\n"
"Constraints: no downtime windows > 5m, PCI scope must shrink, team of 6, 2 quarters.\n"
"Hot paths: checkout (writes orders, payments), search (read-heavy), notifications (async).\n"
"Known landmines: payments code has no tests; search shares the orders DB; a nightly\n"
"cron rebuilds the catalog and pins CPU for ~20m; the replica lags up to 90s under load.\n"
"Org wants: independent deploys for checkout, smaller blast radius, an audit trail.\n"
"Nice to have: event log for orders, read-model for search, feature flags.\n"
"Hard no: a big-bang rewrite; introducing Kubernetes this year.";
auto specialist = axllm::agent(
"brief:string, goal:string -> plan:string[] \"Ordered, concrete steps\", answer:string, risks:string[]",
axllm::object({
{"contextFields", axllm::array({"brief"})},
{"contextPolicy", axllm::object({{"preset", "checkpointed"}, {"budget", "balanced"}})},
{"maxRuntimeChars", 3000},
{"runtime", axllm::object({{"language", "JavaScript"}})},
}));
axllm::runtime::quickjs::QuickJsCodeRuntime runtime;
axllm::Value result = specialist.forward(
client,
axllm::object({
{"brief", brief},
{"goal", "Propose a safe, incremental 2-quarter plan to split checkout out first, respecting the hard constraints."},
}),
axllm::object({{"runtime", axllm::Core::code_runtime_ref(runtime)}, {"max_actor_steps", 12}}));
std::cout << axllm::stringify(result) << "\n";
}C++ Multi-Model Panel
Fans one question across three providers (OpenAI, Gemini, Anthropic), then judges the candidates and synthesizes a single grounded answer.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY,GOOGLE_APIKEY,ANTHROPIC_APIKEY - Level:
advanced - Run:
npm run example -- cpp src/examples/cpp/short-agents/model_panel.cpp - Source: src/examples/cpp/short-agents/model_panel.cpp
#include "axllm/axllm.hpp"
#include <cstdlib>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
static const char* env_or(const char* primary, const char* fallback) {
const char* value = std::getenv(primary);
if (value == nullptr || std::string(value).empty()) value = std::getenv(fallback);
return value;
}
int main() {
const char* openai_key = env_or("OPENAI_API_KEY", "OPENAI_APIKEY");
const char* google_key = env_or("GOOGLE_APIKEY", "GOOGLE_API_KEY");
const char* anthropic_key = env_or("ANTHROPIC_APIKEY", "ANTHROPIC_API_KEY");
if (openai_key == nullptr || std::string(openai_key).empty() ||
google_key == nullptr || std::string(google_key).empty() ||
anthropic_key == nullptr || std::string(anthropic_key).empty()) {
std::cerr << "Set OPENAI_APIKEY, GOOGLE_APIKEY, and ANTHROPIC_APIKEY to run this multi-provider panel.\n";
return 2;
}
// A panel of three different providers, each answering the same question
// independently. Plain ax() composition (no agent runtime): fan out to the
// panel, judge the candidates, then synthesize one grounded answer.
axllm::OpenAICompatibleClient openai(axllm::object({
{"api_key", openai_key},
{"model", "gpt-5.4-mini"},
{"model_config", axllm::object({{"temperature", 0}})},
}));
axllm::GoogleGeminiClient gemini(axllm::object({
{"api_key", google_key},
{"model", "gemini-3.5-flash"},
}));
axllm::AnthropicClient anthropic(axllm::object({
{"api_key", anthropic_key},
{"model", "claude-haiku-4-5"},
}));
std::vector<std::pair<std::string, axllm::AIClient*>> panel = {
{"openai/gpt-5.4-mini", &openai},
{"google/gemini-3.5-flash", &gemini},
{"anthropic/claude-haiku-4.5", &anthropic},
};
auto researcher = axllm::ax("question:string -> answer:string, keyFindings:string[], citations:string[], confidence:number");
researcher.set_instruction("Answer independently. Use evidence. Call out uncertainty. Do not optimize for consensus.");
auto judge = axllm::ax("question:string, candidates:json -> consensus:string[], contradictions:string[], uniqueInsights:string[], blindSpots:string[]");
judge.set_instruction("Compare the candidates. Find agreement, conflicts, missing coverage, and unique useful points.");
auto synthesizer = axllm::ax("question:string, candidates:json, review:json -> answer:string, citations:string[], caveats:string[]");
synthesizer.set_instruction("Write one final answer grounded in the candidates and review. Resolve conflicts explicitly.");
std::string question = "What are the strongest arguments for and against a national carbon tax?";
// Each panelist is a different provider answering independently.
axllm::Value candidates = axllm::Value::array();
for (const auto& member : panel) {
axllm::Value response = researcher.forward(*member.second, axllm::object({{"question", question}}));
axllm::Value candidate = axllm::Core::map_merge(axllm::object({{"model", member.first}}), response);
axllm::Core::append(candidates, candidate);
}
// The judge + synthesizer run on one of the panel clients (OpenAI here).
axllm::AIClient& orchestrator = openai;
axllm::Value review = judge.forward(orchestrator, axllm::object({{"question", question}, {"candidates", candidates}}));
axllm::Value final = synthesizer.forward(
orchestrator,
axllm::object({{"question", question}, {"candidates", candidates}, {"review", review}}));
std::cout << axllm::stringify(final) << "\n";
}