| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Local-first AI agent module for Vix.cpp.
vix::ai::agent provides a small, explicit, and production-oriented foundation for building AI-powered developer tools in C++.
It is designed around:
The current stable public API is:
Agent::run(const AgentRequest &request)Other helpers such as chat(), analyze(), explain(), or run_with_tools() are intentionally not exposed yet as stable APIs.
#include <vix/ai/agent/agent.hpp>This umbrella header exposes the public agent API:
#include <vix/ai/agent/Agent.hpp>
#include <vix/ai/agent/AgentConfig.hpp>
#include <vix/ai/agent/AgentConfigLoader.hpp>
#include <vix/ai/agent/AgentConfigValidator.hpp>
#include <vix/ai/agent/AgentError.hpp>
#include <vix/ai/agent/AgentRequest.hpp>
#include <vix/ai/agent/AgentResponse.hpp>
#include <vix/ai/agent/AgentResult.hpp>
#include <vix/ai/agent/AgentRunStore.hpp>
#include <vix/ai/agent/AgentRunTimer.hpp>
#include <vix/ai/agent/AgentWorkspace.hpp>#include <vix/ai/agent/agent.hpp>
#include <vix/print.hpp>
int main()
{
vix::ai::agent::AgentConfig config;
config.provider = "ollama";
config.model = "llama3";
config.model_url = "http://127.0.0.1:11434";
config.allow_file_read = true;
config.allow_process = false;
config.allow_file_write = false;
vix::ai::agent::Agent agent(config);
vix::ai::agent::AgentRequest request;
request.input = "Explain this project in simple words.";
request.workspace = ".";
request.mode = vix::ai::agent::AgentRequestMode::Analyze;
request.allow_tools = true;
request.allow_file_read = true;
request.allow_process = false;
request.allow_file_write = false;
auto result = agent.run(request);
if (!result)
{
vix::print("Agent error:", result.error().message());
return 1;
}
vix::print(result.value().text);
return 0;
}Vix AI Agent is designed to be:
The agent does not silently read or modify files outside the workspace.
Current stable surface:
Agent::run(...)
Current internal features:
agent/
├── Agent
├── AgentConfig
├── AgentConfigLoader
├── AgentConfigValidator
├── AgentRequest
├── AgentResponse
├── AgentRunStore
├── AgentWorkspace
├── crypto/
│ ├── AgentFingerprint
│ └── AgentId
├── model/
│ ├── ModelProvider
│ ├── ModelRequest
│ ├── ModelResponse
│ └── OllamaProvider
├── tools/
│ ├── Tool
│ ├── ToolCall
│ ├── ToolRegistry
│ ├── ToolResult
│ ├── FileReadTool
│ └── CommandTool
└── workspace/
├── FileReader
├── FileScanPolicy
└── ProjectScanner
Agent is the main orchestrator.
It receives an AgentRequest, prepares the workspace, builds model context, optionally executes controlled tools, and returns an AgentResponse.
vix::ai::agent::Agent agent(config);
auto result = agent.run(request);AgentConfig controls the agent runtime.
vix::ai::agent::AgentConfig config;
config.provider = "ollama";
config.model = "llama3";
config.model_url = "http://127.0.0.1:11434";
config.timeout_ms = 30'000;
config.tool_timeout_ms = 30'000;
config.max_files = 2'000;
config.max_file_size = 512 * 1024;
config.max_tool_output = 20'000;
config.max_context_chars = 120'000;
config.max_tool_rounds = 3;
config.offline = true;
config.allow_file_read = true;
config.allow_process = false;
config.allow_file_write = false;
config.use_cache = true;
config.cache_ttl_ms = 5 * 60 * 1000;
config.persist_memory = true;AgentRequest represents one user request.
vix::ai::agent::AgentRequest request;
request.input = "Explain this project.";
request.workspace = ".";
request.mode = vix::ai::agent::AgentRequestMode::Analyze;
request.allow_tools = true;
request.allow_file_read = true;
request.allow_process = false;
request.allow_file_write = false;
request.use_cache = true;AgentResponse contains the final text, metadata, model information, run id, cache status, and tool summaries.
auto result = agent.run(request);
if (result)
{
const auto &response = result.value();
vix::print("run:", response.run_id);
vix::print("provider:", response.provider);
vix::print("model:", response.model);
vix::print("from cache:", response.from_cache);
vix::print(response.text);
}AgentRequestMode controls the high-level behavior of the request.
request.mode = vix::ai::agent::AgentRequestMode::Run;
request.mode = vix::ai::agent::AgentRequestMode::Analyze;
request.mode = vix::ai::agent::AgentRequestMode::Explain;
request.mode = vix::ai::agent::AgentRequestMode::Chat;| Mode | Purpose |
|---|---|
| Run | Normal single request |
| Analyze | Analyze a workspace or project |
| Explain | Explain something without modifying files |
| Chat | Chat-style interaction |
The default provider is Ollama.
config.provider = "ollama";
config.model = "llama3";
config.model_url = "http://127.0.0.1:11434";The current OllamaProvider targets:
POST /api/generate
Example local setup:
ollama serve
ollama pull llama3Then run your Vix AI Agent program.
The agent is explicit about local capabilities.
config.allow_file_read = true;
config.allow_process = false;
config.allow_file_write = false;Per request, permissions can be restricted further:
request.allow_tools = true;
request.allow_file_read = true;
request.allow_process = false;
request.allow_file_write = false;The effective permission is restrictive.
If the global config disables a capability, the request cannot enable it.
For example, this fails:
config.allow_process = false;
request.allow_process = true;All file operations are resolved through AgentWorkspace.
The workspace protects the agent from reading outside the project root.
It rejects:
Default internal directories:
.vix/agent/memory .vix/agent/cache .vix/agent/runs .vix/agent/logs
FileScanPolicy controls what the agent may scan or read.
It rejects common generated or unsafe paths such as:
.git .vix .cache .idea .vscode build build-ninja build-release build-debug cmake-build-debug cmake-build-release node_modules vendor dist out target __pycache__
It also rejects:
Common allowed extensions include:
.c .cc .cpp .cxx .h .hh .hpp .hxx .cmake .txt .md .json .yaml .yml .toml .js .jsx .ts .tsx .vue .py .rs .go .java .php .rb .sh .zsh .bash .html .css .scss .sql
The agent has a controlled tool system.
Current tools:
| Tool | Purpose |
|---|---|
| file.read | Read a safe text file inside the workspace |
| command.run | Run an allowed local command inside the workspace |
Tools are registered in ToolRegistry.
The agent can execute model-requested tool calls through a controlled loop:
model request tool calls tool execution tool results final model response
Tool name:
file.read
Expected arguments:
{
"path": "src/main.cpp"
}The path is resolved through AgentWorkspace and checked by FileScanPolicy.
Tool name:
command.run
Expected arguments:
{
"program": "vix",
"args": ["build"],
"working_directory": "."
}command.run is disabled by default.
To enable it:
config.allow_process = true;
config.allowed_programs = {
"vix",
"cmake",
"ninja",
"git",
"ls",
"cat",
"echo"
};Programs not present in allowed_programs are rejected.
Dangerous programs are also blocked:
rm rmdir mv dd mkfs shutdown reboot poweroff sudo su
The command working directory must stay inside the workspace.
Important tool-related limits:
config.tool_timeout_ms = 30'000;
config.max_tool_output = 20'000;
config.max_tool_rounds = 3;Current status:
When persist_memory is enabled, the agent stores local run history.
config.persist_memory = true;Run history is written under:
.vix/agent/runs/<run_id>/
A run may include:
run.json prompt.txt model_response.json tools.json response.json response.txt error.json
This makes local debugging, auditing, and replay support easier to build later.
When use_cache is enabled, the agent can reuse safe cached model responses.
config.use_cache = true;
config.cache_ttl_ms = 5 * 60 * 1000;The first cache implementation is conservative:
AgentConfigLoader can load configuration from environment variables.
auto config =
vix::ai::agent::AgentConfigLoader::from_environment();Default prefix:
VIX_AGENT_
Supported variables include:
VIX_AGENT_PROVIDER VIX_AGENT_MODEL VIX_AGENT_MODEL_URL VIX_AGENT_MEMORY_DIR VIX_AGENT_CACHE_DIR VIX_AGENT_RUNS_DIR VIX_AGENT_LOGS_DIR VIX_AGENT_TIMEOUT_MS VIX_AGENT_MAX_FILES VIX_AGENT_MAX_FILE_SIZE VIX_AGENT_MAX_TOOL_OUTPUT VIX_AGENT_MAX_CONTEXT_CHARS VIX_AGENT_OFFLINE VIX_AGENT_ALLOW_PROCESS VIX_AGENT_ALLOW_FILE_READ VIX_AGENT_ALLOW_FILE_WRITE VIX_AGENT_USE_CACHE VIX_AGENT_PERSIST_MEMORY
Example:
export VIX_AGENT_PROVIDER=ollama
export VIX_AGENT_MODEL=llama3
export VIX_AGENT_MODEL_URL=http://127.0.0.1:11434
export VIX_AGENT_ALLOW_PROCESS=falseThen:
auto config = vix::ai::agent::AgentConfigLoader::from_environment();
vix::ai::agent::Agent agent(config);Use AgentConfigValidator to validate a config before running the agent.
vix::ai::agent::AgentConfig config;
auto err = vix::ai::agent::AgentConfigValidator::validate(config);
if (err)
{
vix::print("Invalid config:", err.message());
return 1;
}The agent also validates its configuration at runtime before executing a request.
You can inject your own provider by implementing ModelProvider.
class MyProvider final : public vix::ai::agent::ModelProvider
{
public:
[[nodiscard]] std::string_view name() const noexcept override
{
return "my-provider";
}
[[nodiscard]] bool local() const noexcept override
{
return true;
}
[[nodiscard]] vix::ai::agent::AgentResult<bool> available() const override
{
return true;
}
[[nodiscard]] vix::ai::agent::AgentResult<vix::ai::agent::ModelResponse> generate(
const vix::ai::agent::ModelRequest &request) override
{
vix::ai::agent::ModelResponse response;
response.text = "Hello from my provider";
response.model = request.model;
response.provider = "my-provider";
response.status = vix::ai::agent::ModelResponseStatus::Completed;
return response;
}
};Use it with Agent:
auto provider = std::make_shared<MyProvider>();
vix::ai::agent::Agent agent(config, provider);Create a tool by implementing Tool.
class EchoTool final : public vix::ai::agent::Tool
{
public:
[[nodiscard]] std::string_view name() const noexcept override
{
return "test.echo";
}
[[nodiscard]] std::string_view description() const noexcept override
{
return "Echo test tool.";
}
[[nodiscard]] vix::ai::agent::AgentResult<vix::ai::agent::ToolResult> run(
const vix::ai::agent::ToolCall &call) override
{
return vix::ai::agent::ToolResult::success(
call.id,
"test.echo",
"echo");
}
};Register it:
vix::ai::agent::Agent agent(config);
auto err = agent.tools().add(std::make_shared<EchoTool>());
if (err)
{
vix::print("Tool error:", err.message());
}The agent uses:
vix::ai::agent::AgentResult<T>which is an alias around:
vix::error::Result<T>Example:
auto result = agent.run(request);
if (!result)
{
const auto &err = result.error();
vix::print("error:", err.message());
return 1;
}
vix::print(result.value().text);Agent-specific errors include:
empty_input invalid_workspace path_outside_workspace model_unavailable model_request_failed model_response_invalid tool_not_found tool_not_allowed tool_failed tool_timeout memory_unavailable memory_write_failed memory_read_failed config_invalid internal_failure
From the module directory:
cd ~/vixcpp/vix/modules/agent
cmake --build build-ninja
./build-ninja/vix_ai_agent_testsCurrent test areas:
From the module directory:
cd ~/vixcpp/vix/modules/agent
vix build --build-target all -vFrom the Vix root:
cd ~/vixcpp/vix
vix build --build-target all -v#include <vix/ai/agent/agent.hpp>
#include <vix/print.hpp>
int main()
{
vix::ai::agent::AgentConfig config;
config.provider = "ollama";
config.model = "llama3";
config.model_url = "http://127.0.0.1:11434";
config.allow_file_read = true;
config.allow_process = false;
config.allow_file_write = false;
config.use_cache = true;
config.persist_memory = true;
vix::ai::agent::Agent agent(config);
vix::ai::agent::AgentRequest request;
request.workspace = ".";
request.input = "Explain what this project does.";
request.mode = vix::ai::agent::AgentRequestMode::Analyze;
request.allow_tools = true;
request.allow_file_read = true;
request.allow_process = false;
request.allow_file_write = false;
auto result = agent.run(request);
if (!result)
{
vix::print("Agent failed:", result.error().message());
return 1;
}
vix::print(result.value().text);
return 0;
}MIT
| Back | FazBrowse Home | New Git URL |