BareGit

Reset the repo

Author: MetroWind <chris.corsair@gmail.com>
Date: Sun May 10 15:45:25 2026 -0700
Commit: 16ea26abb1d6a14001f4739c73bd61f0f1e778b2

Changes

diff --git a/CMakeLists.txt b/CMakeLists.txt
deleted file mode 100644
index d5b5028..0000000
--- a/CMakeLists.txt
+++ /dev/null
@@ -1,113 +0,0 @@
-cmake_minimum_required(VERSION 3.24)
-project(AgentSmith)
-
-set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
-set(CMAKE_CXX_STANDARD 23)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_CXX_EXTENSIONS FALSE)
-
-include(FetchContent)
-
-FetchContent_Declare(
-  libmw
-  GIT_REPOSITORY https://github.com/MetroWind/libmw.git
-)
-
-FetchContent_Declare(
-  spdlog
-  GIT_REPOSITORY https://github.com/gabime/spdlog.git
-  GIT_TAG v1.12.0
-)
-
-FetchContent_Declare(
-  json
-  GIT_REPOSITORY https://github.com/nlohmann/json.git
-  GIT_TAG v3.11.3
-)
-
-FetchContent_Declare(
-  cxxopts
-  GIT_REPOSITORY https://github.com/jarro2783/cxxopts.git
-  GIT_TAG v3.1.1
-)
-
-set(SPDLOG_USE_STD_FORMAT ON)
-set(LIBMW_BUILD_URL ON)
-set(LIBMW_BUILD_SQLITE ON)
-set(LIBMW_BUILD_HTTP_SERVER OFF)
-set(LIBMW_BUILD_CRYPTO OFF)
-
-FetchContent_MakeAvailable(libmw spdlog json cxxopts)
-
-set(LIB_SOURCE_FILES
-    src/agent.cpp
-    src/llm_client.cpp
-    src/memory.cpp
-    src/tool.cpp
-    src/message.cpp
-)
-
-set(LIBS
-    mw::mw
-    mw::url
-    mw::sqlite
-    spdlog::spdlog
-    nlohmann_json::nlohmann_json
-)
-
-set(INCLUDES
-    ${libmw_SOURCE_DIR}/includes
-    ${json_SOURCE_DIR}/single_include
-)
-
-# 1. Build the Agent Smith Library
-add_library(agent_smith ${LIB_SOURCE_FILES})
-set_property(TARGET agent_smith PROPERTY CXX_STANDARD 23)
-target_compile_options(agent_smith PRIVATE -Wall -Wextra)
-target_include_directories(agent_smith PUBLIC ${INCLUDES} src)
-target_link_libraries(agent_smith PUBLIC ${LIBS})
-
-# 2. Build the Example CLI Executable
-add_executable(agent_smith_cli src/main.cpp)
-set_property(TARGET agent_smith_cli PROPERTY CXX_STANDARD 23)
-target_compile_options(agent_smith_cli PRIVATE -Wall -Wextra)
-target_include_directories(agent_smith_cli PRIVATE ${cxxopts_SOURCE_DIR}/include)
-target_link_libraries(agent_smith_cli PRIVATE agent_smith cxxopts::cxxopts)
-
-option(AGENT_SMITH_BUILD_TESTS "Build unit tests" ON)
-
-if(AGENT_SMITH_BUILD_TESTS)
-  FetchContent_Declare(
-    googletest
-    URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz
-  )
-  FetchContent_MakeAvailable(googletest)
-
-  set(TEST_FILES
-    src/task_test.cpp
-    src/memory_test.cpp
-    src/tool_test.cpp
-    src/agent_test.cpp
-    src/llm_client_test.cpp
-    src/message_test.cpp
-  )
-
-  add_executable(agent_smith_test ${TEST_FILES})
-  
-  set_property(TARGET agent_smith_test PROPERTY CXX_STANDARD 23)
-  target_compile_options(agent_smith_test PRIVATE -Wall -Wextra)
-  target_include_directories(agent_smith_test PRIVATE 
-    ${googletest_SOURCE_DIR}/googletest/include
-    ${googletest_SOURCE_DIR}/googlemock/include
-  )
-
-  target_link_libraries(agent_smith_test PRIVATE
-    agent_smith
-    GTest::gtest_main
-    GTest::gmock_main
-  )
-
-  enable_testing()
-  include(GoogleTest)
-  gtest_discover_tests(agent_smith_test)
-endif()
diff --git a/README.md b/README.md
deleted file mode 100644
index 896ae4d..0000000
--- a/README.md
+++ /dev/null
@@ -1,128 +0,0 @@
-# Agent Smith 🕶️
-
-**Agent Smith** is a high-performance, modular C++23 framework for building LLM-powered agents. 
-
-Designed with composability and safety in mind, it provides a clean, dependency-injectable architecture for orchestrating LLM interactions, managing conversation history, and natively executing tools/functions.
-
-## Key Features
-
-*   **Modular Architecture:** Swap out LLM clients, memory storage backends, and tool registries effortlessly.
-*   **Native Tool Calling:** Fully supports structured JSON tool calling, paving the way for seamless Model Context Protocol (MCP) integrations.
-*   **Exception-Free Error Handling:** Built heavily around C++23 `std::expected` (via `mw::E<T>`), ensuring robust network and execution error propagation without crashing your application.
-*   **Async-Ready:** Core loops and LLM executions return `Task<T>` coroutine wrappers, ready for integration into modern async event loops.
-*   **Lightweight Foundation:** Powered by `libmw` for everyday HTTP networking and data handling, alongside `nlohmann/json` and `spdlog`.
-
-## Integration
-
-Agent Smith is designed to be consumed as a CMake library. The easiest way to add it to your project is via `FetchContent`.
-
-### CMakeLists.txt
-
-```cmake
-include(FetchContent)
-
-FetchContent_Declare(
-  agent_smith
-  GIT_REPOSITORY https://github.com/YourOrg/agent-smith.git
-  # GIT_TAG main
-)
-
-FetchContent_MakeAvailable(agent_smith)
-
-add_executable(my_agent src/main.cpp)
-target_link_libraries(my_agent PRIVATE agent_smith)
-```
-
-## Quick Start Example
-
-Here is a minimal example of how to configure an OpenAI-compatible client, define a custom tool, and run an agent loop.
-
-```cpp
-#include <iostream>
-#include <memory>
-#include <agent.hpp>
-#include <llm_client.hpp>
-#include <memory.hpp>
-#include <tool.hpp>
-
-// 1. Define a custom tool
-class MyCalculator : public Tool {
-public:
-    std::string name() const override { return "calculator"; }
-    std::string description() const override { return "Performs basic addition."; }
-    
-    nlohmann::json parametersSchema() const override {
-        return R"({
-            "type": "object",
-            "properties": {
-                "a": {"type": "number"},
-                "b": {"type": "number"}
-            },
-            "required": ["a", "b"]
-        })"_json;
-    }
-    
-    Task<mw::E<std::string>> execute(const nlohmann::json& args) override {
-        double a = args["a"];
-        double b = args["b"];
-        co_return std::to_string(a + b);
-    }
-};
-
-// Simple blocking runner for coroutines
-void runTask(Task<mw::E<std::string>> task) {
-    auto res = task.get();
-    if(res.has_value()) std::cout << "Agent: " << res.value() << "
-";
-    else std::cout << "Error: " << mw::errorMsg(res.error()) << "
-";
-}
-
-int main() {
-    // 2. Setup the infrastructure
-    auto client = std::make_unique<OpenAiClient>("your-api-key");
-    auto memory = std::make_unique<InMemoryMemory>();
-    ToolRegistry registry;
-    
-    registry.registerTool(std::make_unique<MyCalculator>());
-    
-    // 3. Instantiate the agent
-    Agent agent(std::move(client), std::move(memory), registry);
-    agent.allowTool("calculator");
-    
-    Skill math_skill{
-        "math_bot", 
-        "You are a helpful math bot. Use your tools to answer questions.", 
-        {"calculator"}
-    };
-    agent.activateSkill(math_skill);
-    
-    // 4. Run the conversational loop
-    runTask(agent.run("What is 42 + 8?"));
-    
-    return 0;
-}
-```
-
-## Built-in CLI
-
-The repository also builds an interactive CLI executable (`agent_smith_cli`) out of the box, which serves as a great reference implementation.
-
-```bash
-# Build the CLI and tests
-cmake -S . -B build
-cmake --build build -j
-
-# Run the CLI using a custom local endpoint
-./build/agent_smith_cli --api-key "dummy" --endpoint "http://localhost:8080/v1" --model "local-model"
-```
-
-## Dependencies
-
-*   **C++ Standard:** C++23
-*   **Build System:** CMake >= 3.24
-*   [libmw](https://github.com/MetroWind/libmw) (HTTP client, SQLite, core utils)
-*   [nlohmann/json](https://github.com/nlohmann/json)
-*   [spdlog](https://github.com/gabime/spdlog)
-*   [cxxopts](https://github.com/jarro2783/cxxopts) (CLI only)
-*   [GoogleTest](https://github.com/google/googletest) (Tests only)
diff --git a/design.md b/design.md
deleted file mode 100644
index 61a57ec..0000000
--- a/design.md
+++ /dev/null
@@ -1,311 +0,0 @@
-# Technical Design Document: Agent Smith Framework
-
-## 1. Introduction
-This document outlines the technical design for **Agent Smith**, a modular C++23 framework for building LLM-powered agents. It is designed to be highly efficient and leverages `libmw` for everyday system tasks, networking, and data handling. 
-
-This guide is structured to help a new graduate software engineer understand the architecture and implement the system systematically.
-
----
-
-## 2. High-Level Architecture
-The framework relies on a decoupled architecture centered around the `Agent` class.
-
-*   **`Agent`**: The orchestrator. It manages the conversational loop, maintains state via `Memory`, interacts with the `LlmClient`, and dynamically executes `Tools` and `Skills`.
-*   **`LlmClient`**: Handles network communication with LLM APIs (OpenAI and Gemini) using `mw::url`.
-*   **`Memory`**: Stores the conversation history. Can be in-memory or backed by `mw::sqlite` for persistence.
-*   **`Tool`**: An interface representing a callable action. Includes native tools and integrations via the Model Context Protocol (MCP).
-*   **`Skill`**: A configuration that bundles a specific system prompt and a subset of tools to focus the agent on a specific workflow.
-*   **CLI**: A command-line interface implemented using `cxxopts` to allow users to configure the agent's connection parameters (API key and endpoint) at runtime.
-
----
-
-## 3. Data Models
-
-We use `nlohmann/json` (provided via `libmw`) for all dynamic data structures and serialization.
-
-```cpp
-#include <string>
-#include <optional>
-#include <vector>
-#include <variant>
-#include <nlohmann/json.hpp>
-
-// 1. System Message: Defines the agent's persona and overarching rules.
-struct SystemMessage
-{
-    std::string content;
-};
-
-// 2. User Message: Input provided by the human user.
-struct UserMessage
-{
-    std::string content;
-};
-
-// Represents a single tool call requested by the Assistant
-struct ToolCall
-{
-    std::string id;
-    std::string name;
-    nlohmann::json arguments;
-};
-
-// 3. Assistant Message: The LLM's response. Can contain text or tool calls.
-struct AssistantMessage
-{
-    std::optional<std::string> content;
-    std::vector<ToolCall> tool_calls; 
-};
-
-// 4. Tool Result Message: The result of executing a tool, sent back to LLM.
-struct ToolResultMessage
-{
-    std::string tool_call_id;
-    std::string content;
-};
-
-// The unified Message type using std::variant for compile-time type safety.
-using Message = std::variant<
-    SystemMessage, 
-    UserMessage, 
-    AssistantMessage, 
-    ToolResultMessage>;
-
-// Standalone serialization functions for each message type
-nlohmann::json toJson(const SystemMessage& msg);
-nlohmann::json toJson(const UserMessage& msg);
-nlohmann::json toJson(const ToolCall& msg);
-nlohmann::json toJson(const AssistantMessage& msg);
-nlohmann::json toJson(const ToolResultMessage& msg);
-nlohmann::json toJson(const Message& msg);
-```
-
----
-
-## 4. Component Design
-
-### 4.1 LlmClient Interface
-The `LlmClient` abstracts the underlying LLM provider. This component uses `mw::E<>` for explicit error handling and C++23 coroutines for asynchronous task management.
-
-```cpp
-#include <mw/error.hpp>
-
-// A placeholder for a C++23 coroutine Task type. 
-template<typename T> class Task; 
-
-class LlmClient
-{
-public:
-    virtual ~LlmClient() = default;
-    
-    // Submits the history and tools, returning the Assistant's response or an error
-    virtual Task<mw::E<Message>> generateResponse(
-        const std::vector<Message>& history, 
-        const nlohmann::json& available_tools_schema
-    ) = 0;
-};
-```
-*   **Implementation Steps:**
-    *   Implement `OpenAiClient`. Allow dependency injection of `mw::HTTPSessionInterface` (falling back to `mw::HTTPSession`) to enable rigorous mocked network testing.
-    *   Use `mw::URL` to safely parse custom endpoints and append standard paths (like `chat/completions`).
-    *   Deserialize the response body into the `Message` struct, utilizing `std::unexpected(mw::runtimeError(...))` on JSON parsing failures.
-
-### 4.2 Tool and MCP System
-A `Tool` must expose its JSON Schema so the LLM understands its parameters, and an execution method.
-
-```cpp
-class Tool
-{
-public:
-    virtual ~Tool() = default;
-    virtual std::string name() const = 0;
-    virtual std::string description() const = 0;
-    
-    // Returns the JSON Schema describing the arguments the tool accepts
-    virtual nlohmann::json parametersSchema() const = 0;
-    
-    // Executes the tool with the JSON arguments provided by the LLM
-    virtual Task<mw::E<std::string>> execute(const nlohmann::json& arguments) = 0;
-};
-```
-
-**Tool Registry:**
-To support multiple agents and centralized tool management, tools are owned by a global or application-level `ToolRegistry`. Methods returning `mw::E<void>` signal success or report duplication errors.
-
-```cpp
-#include <unordered_map>
-#include <memory>
-#include <stdexcept>
-#include <format>
-
-class ToolRegistry
-{
-public:
-    // Registers a tool. Throws an exception if the tool name already exists
-    // to prevent silent collisions.
-    void registerTool(std::unique_ptr<Tool> tool)
-    {
-        if(tools_.contains(tool->name()))
-        {
-            throw std::runtime_error(
-                std::format("Tool '{}' is already registered.", tool->name()));
-        }
-        tools_[tool->name()] = std::move(tool);
-    }
-
-    // Registers a tool with a namespace prefix to avoid collisions
-    // (e.g., from different MCP servers).
-    void registerToolWithNamespace(
-        const std::string& ns, 
-        std::unique_ptr<Tool> tool)
-    {
-        // Implementation detail: The Tool interface or a wrapper class
-        // would need to return the new name when name() is called.
-        std::string prefixed_name = std::format("{}_{}", ns, tool->name());
-        if(tools_.contains(prefixed_name))
-        {
-            throw std::runtime_error(
-                std::format("Tool '{}' is already registered.", prefixed_name));
-        }
-        // ... wrap tool and store with prefixed_name
-    }
-
-    Tool* getTool(const std::string& name) const
-    {
-        auto it = tools_.find(name);
-        return it != tools_.end() ? it->second.get() : nullptr;
-    }
-    
-    std::vector<Tool*> getAllTools() const
-    {
-        std::vector<Tool*> result;
-        for(const auto& [name, tool] : tools_)
-        {
-            result.push_back(tool.get());
-        }
-        return result;
-    }
-
-private:
-    std::unordered_map<std::string, std::unique_ptr<Tool>> tools_;
-};
-```
-
-*   **Handling Collisions & Namespacing:** LLMs require unique tool names. If an MCP server provides a tool named `search` and another server also provides `search`, the `ToolRegistry` will reject the second registration. To resolve this, external tools (like those from MCP) should be registered using `registerToolWithNamespace` (e.g., `github_search` vs `local_search`).
-*   **MCP Integration:** 
-    *   Implement an `McpClient` that can parse MCP server manifests.
-    *   The `McpClient` will act as a factory, dynamically generating `Tool` objects that map to remote MCP functions and registering them with the `ToolRegistry` using the server's name as a namespace.
-
-### 4.3 Agent Skills
-A `Skill` overrides the agent's default behavior, giving it a new persona and restricted capabilities.
-
-```cpp
-struct Skill
-{
-    std::string name;
-    std::string system_prompt;
-    // Names of the tools allowed for this skill
-    std::vector<std::string> allowed_tools; 
-};
-```
-
-### 4.4 Memory Management
-Handles the context window.
-
-```cpp
-class Memory
-{
-public:
-    virtual ~Memory() = default;
-    virtual void addMessage(const Message& msg) = 0;
-    virtual std::vector<Message> getHistory() const = 0;
-    virtual void clear() = 0;
-};
-```
-*   **Implementation Steps:**
-    *   Create `InMemoryMemory` (a simple `std::vector` wrapper).
-    *   Create `SqliteMemory` using `mw::sqlite` to persist `Message` structs to a database file.
-
-### 4.5 The Agent Core
-The `Agent` ties the components together in its main conversational loop.
-
-```cpp
-#include <memory>
-#include <vector>
-
-class Agent
-{
-public:
-    Agent(
-        std::unique_ptr<LlmClient> client, 
-        std::unique_ptr<Memory> memory, 
-        ToolRegistry& tool_registry);
-    
-    // Grants the agent permission to use a specific tool from the registry
-    mw::E<void> allowTool(const std::string& tool_name);
-    void activateSkill(const Skill& skill);
-    
-    // The main entry point for user interaction
-    Task<mw::E<std::string>> run(const std::string& user_input);
-    
-private:
-    std::unique_ptr<LlmClient> client_;
-    std::unique_ptr<Memory> memory_;
-    ToolRegistry& tool_registry_;
-    
-    // List of tool names this agent is currently allowed to use
-    std::vector<std::string> allowed_tools_;
-    std::optional<Skill> current_skill_;
-};
-```
-
-**The `run` Loop Logic (Pseudo-code):**
-1. Append `user_input` as a `UserMessage` to `memory_`.
-2. `loop`:
-    1. Fetch `history` from `memory_`.
-    2. Resolve `allowed_tools_` against the `tool_registry_` and convert them into a single JSON Schema array.
-    3. `response_msg = co_await client_->generateResponse(history, tools_schema)`.
-    4. Append `response_msg` (which is an `AssistantMessage`) to `memory_`.
-    5. `if response_msg contains tool_calls`:
-        1. For each `call` in `tool_calls`:
-            1. Find matching `Tool* tool` in `tool_registry_`.
-            2. `result = co_await tool->execute(call.arguments)`.
-            3. Append a `ToolResultMessage` (containing `result` and `call.id`) to `memory_`.
-    6. `else`:
-        1. Break loop.
-3. Return `response_msg.content` (or extract content from the variant).
-
----
-
-## 5. Build System & Dependencies
-*   **CMake:** The project will be built using CMake (`CMakeLists.txt`).
-*   **C++23:** Ensure compiler flags support standard C++23 (`-std=c++23`).
-*   **libmw:** Include `libmw` via `FetchContent` or as a Git submodule. 
-    *   Link against `mw::core`, `mw::url`, `mw::sqlite`.
-*   **Logging:** Use `spdlog` (bundled with `libmw`) for detailed debug and execution logging.
-
----
-
-## 6. Implementation Plan (For the Developer)
-
-To build this systematically, follow these phases:
-
-1.  **Phase 1: Foundations & Build Setup** 
-    *   Create the `CMakeLists.txt`. Integrate `libmw`. 
-    *   Define the core structs (`Message`, `Role`, `Skill`).
-2.  **Phase 2: Networking & LLM Client** 
-    *   Implement the `LlmClient` interface. 
-    *   Build `OpenAiClient` using `mw::url`. Test it with a hardcoded prompt to ensure you can parse the JSON responses.
-3.  **Phase 3: The Core Loop** 
-    *   Implement the `Agent` class and a simple `InMemoryMemory` class. 
-    *   Get a basic back-and-forth chat working in the terminal *without* tools.
-4.  **Phase 4: Tool Calling** 
-    *   Implement the `Tool` interface. 
-    *   Create a simple mock tool (e.g., `CalculatorTool`). 
-    *   Implement the `Agent::run` loop logic to parse tool calls, execute them, and feed the results back to the LLM.
-5.  **Phase 5: Persistence & Skills** 
-    *   Implement `SqliteMemory` utilizing `mw::sqlite`.
-    *   Add the ability to load and switch between `Skill` profiles.
-6.  **Phase 6: Async Polish & MCP** 
-    *   Finalize C++23 coroutine integration for all network and execution paths.
-    *   Research and implement an `McpClient` to communicate with external MCP servers over stdio.
\ No newline at end of file
diff --git a/src/agent.cpp b/src/agent.cpp
deleted file mode 100644
index 54060db..0000000
--- a/src/agent.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-#include "agent.hpp"
-
-#include <spdlog/spdlog.h>
-
-Agent::Agent(std::unique_ptr<LlmClient> client, std::unique_ptr<Memory> memory,
-             ToolRegistry& tool_registry)
-    : client_(std::move(client)), memory_(std::move(memory)),
-      tool_registry_(tool_registry)
-{
-}
-
-mw::E<void> Agent::allowTool(const std::string& tool_name)
-{
-    if(tool_registry_.getTool(tool_name) == nullptr)
-    {
-        return std::unexpected(mw::runtimeError("Tool not found in registry"));
-    }
-    allowed_tools_.push_back(tool_name);
-    return {};
-}
-
-void Agent::activateSkill(const Skill& skill)
-{
-    current_skill_ = skill;
-    allowed_tools_ = skill.allowed_tools;
-    memory_->addMessage(SystemMessage{skill.system_prompt});
-}
-
-Task<mw::E<std::string>> Agent::run(const std::string& user_input)
-{
-    memory_->addMessage(UserMessage{user_input});
-
-    while(true)
-    {
-        auto history = memory_->getHistory();
-        nlohmann::json tools_schema = nlohmann::json::array();
-
-        for(const auto& tool_name : allowed_tools_)
-        {
-            if(Tool* tool = tool_registry_.getTool(tool_name))
-            {
-                nlohmann::json tool_json = {
-                    {"type", "function"},
-                    {"function",
-                     {{"name", tool->name()},
-                      {"description", tool->description()},
-                      {"parameters", tool->parametersSchema()}}}};
-                tools_schema.push_back(tool_json);
-            }
-        }
-
-        auto response_res =
-            co_await client_->generateResponse(history, tools_schema);
-        if(!response_res.has_value())
-        {
-            co_return std::unexpected(response_res.error());
-        }
-
-        Message response_msg = response_res.value();
-        memory_->addMessage(response_msg);
-
-        auto& assistant_msg = std::get<AssistantMessage>(response_msg);
-
-        if(!assistant_msg.tool_calls.empty())
-        {
-            for(const auto& call : assistant_msg.tool_calls)
-            {
-                if(Tool* tool = tool_registry_.getTool(call.name))
-                {
-                    auto result = co_await tool->execute(call.arguments);
-                    if(result.has_value())
-                    {
-                        memory_->addMessage(
-                            ToolResultMessage{call.id, result.value()});
-                    }
-                    else
-                    {
-                        memory_->addMessage(ToolResultMessage{
-                            call.id, "Error: " + mw::errorMsg(result.error())});
-                    }
-                }
-                else
-                {
-                    memory_->addMessage(
-                        ToolResultMessage{call.id, "Error: Tool not found"});
-                }
-            }
-        }
-        else
-        {
-            if(assistant_msg.content)
-            {
-                co_return *assistant_msg.content;
-            }
-            co_return "";
-        }
-    }
-}
diff --git a/src/agent.hpp b/src/agent.hpp
deleted file mode 100644
index 6a6622e..0000000
--- a/src/agent.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#pragma once
-
-#include <memory>
-#include <optional>
-#include <string>
-#include <vector>
-
-#include <mw/error.hpp>
-
-#include "message.hpp"
-#include "llm_client.hpp"
-#include "memory.hpp"
-#include "task.hpp"
-#include "tool.hpp"
-
-class Agent
-{
-public:
-    Agent(std::unique_ptr<LlmClient> client, std::unique_ptr<Memory> memory,
-          ToolRegistry& tool_registry);
-
-    mw::E<void> allowTool(const std::string& tool_name);
-    void activateSkill(const Skill& skill);
-
-    Task<mw::E<std::string>> run(const std::string& user_input);
-
-private:
-    std::unique_ptr<LlmClient> client_;
-    std::unique_ptr<Memory> memory_;
-    ToolRegistry& tool_registry_;
-
-    std::vector<std::string> allowed_tools_;
-    std::optional<Skill> current_skill_;
-};
diff --git a/src/agent_test.cpp b/src/agent_test.cpp
deleted file mode 100644
index 02de426..0000000
--- a/src/agent_test.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-#include <gtest/gtest.h>
-
-#include "agent.hpp"
-#include "llm_client.hpp"
-#include "memory.hpp"
-#include "tool.hpp"
-
-class MockLlmClient : public LlmClient
-{
-public:
-    std::vector<Message> responses;
-    size_t call_count = 0;
-
-    Task<mw::E<Message>> generateResponse(const std::vector<Message>&,
-                                          const nlohmann::json&) override
-    {
-        if(call_count < responses.size())
-        {
-            auto res = responses[call_count++];
-            co_return res;
-        }
-        co_return AssistantMessage{"default_mock_end", {}};
-    }
-};
-
-class DummyTool : public Tool
-{
-public:
-    std::string name() const override
-    {
-        return "dummy";
-    }
-    std::string description() const override
-    {
-        return "dummy desc";
-    }
-    nlohmann::json parametersSchema() const override
-    {
-        return nlohmann::json::object();
-    }
-    Task<mw::E<std::string>> execute(const nlohmann::json&) override
-    {
-        co_return "dummy_result";
-    }
-};
-
-TEST(AgentTest, BasicRunAndReturn)
-{
-    auto client = std::make_unique<MockLlmClient>();
-    client->responses.push_back(AssistantMessage{"Hello from Agent", {}});
-
-    auto memory = std::make_unique<InMemoryMemory>();
-    ToolRegistry registry;
-
-    Agent agent(std::move(client), std::move(memory), registry);
-
-    auto result = agent.run("Hi").get();
-    ASSERT_TRUE(result.has_value());
-    EXPECT_EQ(result.value(), "Hello from Agent");
-}
-
-TEST(AgentTest, ToolCallingFlow)
-{
-    auto client = std::make_unique<MockLlmClient>();
-
-    AssistantMessage tool_call_msg;
-    tool_call_msg.tool_calls.push_back(
-        {"call_1", "dummy", nlohmann::json::object()});
-
-    client->responses.push_back(tool_call_msg);
-    client->responses.push_back(AssistantMessage{"Final Result", {}});
-
-    auto memory = std::make_unique<InMemoryMemory>();
-    ToolRegistry registry;
-    registry.registerTool(std::make_unique<DummyTool>());
-
-    Agent agent(std::move(client), std::move(memory), registry);
-    agent.allowTool("dummy");
-
-    auto result = agent.run("Hi").get();
-    ASSERT_TRUE(result.has_value());
-    EXPECT_EQ(result.value(), "Final Result");
-}
-
-TEST(AgentTest, ActivateSkill)
-{
-    auto client = std::make_unique<MockLlmClient>();
-    client->responses.push_back(AssistantMessage{"Skill Active", {}});
-
-    auto memory = std::make_unique<InMemoryMemory>();
-    auto* mem_ptr = memory.get();
-    ToolRegistry registry;
-
-    Agent agent(std::move(client), std::move(memory), registry);
-
-    Skill test_skill{"test_skill", "You are a tester", {}};
-    agent.activateSkill(test_skill);
-
-    auto history = mem_ptr->getHistory();
-    ASSERT_EQ(history.size(), 1);
-    EXPECT_TRUE(std::holds_alternative<SystemMessage>(history[0]));
-    EXPECT_EQ(std::get<SystemMessage>(history[0]).content, "You are a tester");
-}
diff --git a/src/calculator_tool.hpp b/src/calculator_tool.hpp
deleted file mode 100644
index 37921ed..0000000
--- a/src/calculator_tool.hpp
+++ /dev/null
@@ -1,81 +0,0 @@
-#pragma once
-
-#include <string>
-
-#include "tool.hpp"
-
-class CalculatorTool : public Tool
-{
-public:
-    std::string name() const override
-    {
-        return "calculator";
-    }
-
-    std::string description() const override
-    {
-        return "Performs basic arithmetic operations.";
-    }
-
-    nlohmann::json parametersSchema() const override
-    {
-        return R"({
-            "type": "object",
-            "properties": {
-                "operation": {
-                    "type": "string",
-                    "enum": ["add", "subtract", "multiply", "divide"],
-                    "description": "The operation to perform"
-                },
-                "a": {
-                    "type": "number"
-                },
-                "b": {
-                    "type": "number"
-                }
-            },
-            "required": ["operation", "a", "b"]
-        })"_json;
-    }
-
-    Task<mw::E<std::string>> execute(const nlohmann::json& arguments) override
-    {
-        if(!arguments.contains("operation") || !arguments.contains("a") ||
-           !arguments.contains("b"))
-        {
-            co_return std::unexpected(mw::runtimeError("Missing arguments"));
-        }
-
-        std::string op = arguments["operation"];
-        double a = arguments["a"];
-        double b = arguments["b"];
-        double result = 0.0;
-
-        if(op == "add")
-        {
-            result = a + b;
-        }
-        else if(op == "subtract")
-        {
-            result = a - b;
-        }
-        else if(op == "multiply")
-        {
-            result = a * b;
-        }
-        else if(op == "divide")
-        {
-            if(b == 0)
-            {
-                co_return std::unexpected(mw::runtimeError("Division by zero"));
-            }
-            result = a / b;
-        }
-        else
-        {
-            co_return std::unexpected(mw::runtimeError("Unknown operation"));
-        }
-
-        co_return std::to_string(result);
-    }
-};
diff --git a/src/llm_client.cpp b/src/llm_client.cpp
deleted file mode 100644
index 16a0c79..0000000
--- a/src/llm_client.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-#include "llm_client.hpp"
-
-#include <mw/http_client.hpp>
-#include <mw/url.hpp>
-#include <spdlog/spdlog.h>
-
-OpenAiClient::OpenAiClient(std::string api_key, std::string model,
-                           std::string endpoint,
-                           std::unique_ptr<mw::HTTPSessionInterface> session)
-    : api_key_(std::move(api_key)), model_(std::move(model)),
-      endpoint_(std::move(endpoint)),
-      session_(session ? std::move(session)
-                       : std::make_unique<mw::HTTPSession>())
-{
-}
-
-mw::E<AssistantMessage>
-OpenAiClient::parseResponse(std::string_view response_body) const
-{
-    try
-    {
-        auto response_json = nlohmann::json::parse(response_body);
-        if(!response_json.contains("choices") || response_json["choices"].empty())
-        {
-            return std::unexpected(mw::runtimeError(
-                std::string("Invalid response format: missing choices. Body: ") + std::string(response_body)));
-        }
-        auto& choice = response_json["choices"][0]["message"];
-
-        AssistantMessage assistant_msg;
-        if(choice.contains("content") && !choice["content"].is_null())
-        {
-            assistant_msg.content = static_cast<std::string>(choice["content"]);
-        }
-
-        if(choice.contains("tool_calls"))
-        {
-            for(const auto& tc : choice["tool_calls"])
-            {
-                ToolCall call;
-                call.id = static_cast<std::string>(tc["id"]);
-                call.name = static_cast<std::string>(tc["function"]["name"]);
-                call.arguments = nlohmann::json::parse(
-                    static_cast<std::string>(tc["function"]["arguments"]));
-                assistant_msg.tool_calls.push_back(call);
-            }
-        }
-
-        return assistant_msg;
-    }
-    catch(const std::exception& e)
-    {
-        return std::unexpected(
-            mw::runtimeError(std::string("JSON parse error: ") + e.what()));
-    }
-}
-
-Task<mw::E<Message>>
-OpenAiClient::generateResponse(const std::vector<Message>& history,
-                               const nlohmann::json& available_tools_schema)
-{
-    nlohmann::json request_body;
-    request_body["model"] = model_;
-
-    nlohmann::json messages = nlohmann::json::array();
-    for(const auto& msg : history)
-    {
-        messages.push_back(toJson(msg));
-    }
-    request_body["messages"] = messages;
-
-    if(!available_tools_schema.empty() && available_tools_schema.is_array())
-    {
-        request_body["tools"] = available_tools_schema;
-    }
-
-    auto url_res = mw::URL::fromStr(endpoint_);
-    if(!url_res.has_value())
-    {
-        co_return std::unexpected(mw::runtimeError("Invalid endpoint URL"));
-    }
-    mw::URL request_url = std::move(url_res.value());
-    request_url.appendPath("chat/completions");
-
-    mw::HTTPRequest request(request_url.str());
-    request.addHeader("Content-Type", "application/json");
-    request.addHeader("Authorization", "Bearer " + api_key_);
-    request.setPayload(request_body.dump());
-
-    auto response = session_->post(request);
-    if(!response.has_value())
-    {
-        spdlog::error("OpenAI request failed: {}",
-                      mw::errorMsg(response.error()));
-        co_return std::unexpected(response.error());
-    }
-
-    auto parsed = parseResponse(response.value()->payloadAsStr());
-    if(!parsed.has_value())
-    {
-        co_return std::unexpected(parsed.error());
-    }
-    co_return parsed.value();
-}
diff --git a/src/llm_client.hpp b/src/llm_client.hpp
deleted file mode 100644
index c2234c2..0000000
--- a/src/llm_client.hpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#pragma once
-
-#include <memory>
-#include <string_view>
-#include <vector>
-
-#include <mw/error.hpp>
-#include <mw/http_client.hpp>
-#include <nlohmann/json.hpp>
-
-#include "message.hpp"
-#include "task.hpp"
-
-class LlmClient
-{
-public:
-    virtual ~LlmClient() = default;
-
-    virtual Task<mw::E<Message>>
-    generateResponse(const std::vector<Message>& history,
-                     const nlohmann::json& available_tools_schema) = 0;
-};
-
-class OpenAiClient : public LlmClient
-{
-public:
-    OpenAiClient(
-        std::string api_key, std::string model = "gpt-4o",
-        std::string endpoint = "https://api.openai.com/v1",
-        std::unique_ptr<mw::HTTPSessionInterface> session = nullptr);
-
-    Task<mw::E<Message>>
-    generateResponse(const std::vector<Message>& history,
-                     const nlohmann::json& available_tools_schema) override;
-
-private:
-    std::string api_key_;
-    std::string model_;
-    std::string endpoint_;
-    std::unique_ptr<mw::HTTPSessionInterface> session_;
-
-    mw::E<AssistantMessage> parseResponse(std::string_view response_body) const;
-};
diff --git a/src/llm_client_test.cpp b/src/llm_client_test.cpp
deleted file mode 100644
index 22881f9..0000000
--- a/src/llm_client_test.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <mw/http_client_mock.hpp>
-
-#include "llm_client.hpp"
-
-using ::testing::_;
-using ::testing::Return;
-
-TEST(OpenAiClientTest, SuccessfulGeneration)
-{
-    auto mock_session = std::make_unique<mw::HTTPSessionMock>();
-
-    std::string mock_json_response = R"({
-        "choices": [
-            {
-                "message": {
-                    "role": "assistant",
-                    "content": "Hello! How can I help?"
-                }
-            }
-        ]
-    })";
-
-    mw::HTTPResponse http_response(200, mock_json_response);
-
-    EXPECT_CALL(*mock_session, post(_)).WillOnce(Return(&http_response));
-
-    OpenAiClient client("fake_key", "gpt-4o", "https://fake.endpoint.com/v1", std::move(mock_session));
-
-    std::vector<Message> history = {UserMessage{"Hi"}};
-    nlohmann::json tools = nlohmann::json::array();
-
-    auto result = client.generateResponse(history, tools).get();
-    ASSERT_TRUE(result.has_value());
-
-    auto& assistant_msg = std::get<AssistantMessage>(result.value());
-    ASSERT_TRUE(assistant_msg.content.has_value());
-    EXPECT_EQ(*assistant_msg.content, "Hello! How can I help?");
-    EXPECT_TRUE(assistant_msg.tool_calls.empty());
-}
-
-TEST(OpenAiClientTest, ToolCallGeneration)
-{
-    auto mock_session = std::make_unique<mw::HTTPSessionMock>();
-
-    std::string mock_json_response = R"({
-        "choices": [
-            {
-                "message": {
-                    "role": "assistant",
-                    "content": null,
-                    "tool_calls": [
-                        {
-                            "id": "call_123",
-                            "type": "function",
-                            "function": {
-                                "name": "calculator",
-                                "arguments": "{\"a\": 2, \"b\": 2, \"operation\": \"add\"}"
-                            }
-                        }
-                    ]
-                }
-            }
-        ]
-    })";
-
-    mw::HTTPResponse http_response(200, mock_json_response);
-
-    EXPECT_CALL(*mock_session, post(_)).WillOnce(Return(&http_response));
-
-    OpenAiClient client("fake_key", "gpt-4o", "https://fake.endpoint.com/v1", std::move(mock_session));
-
-    std::vector<Message> history = {UserMessage{"Calculate 2+2"}};
-    nlohmann::json tools = nlohmann::json::array();
-
-    auto result = client.generateResponse(history, tools).get();
-    ASSERT_TRUE(result.has_value());
-
-    auto& assistant_msg = std::get<AssistantMessage>(result.value());
-    EXPECT_FALSE(assistant_msg.content.has_value());
-    ASSERT_EQ(assistant_msg.tool_calls.size(), 1);
-    EXPECT_EQ(assistant_msg.tool_calls[0].name, "calculator");
-    EXPECT_EQ(assistant_msg.tool_calls[0].arguments["a"], 2);
-}
-
-TEST(OpenAiClientTest, NetworkFailureReturnsError)
-{
-    auto mock_session = std::make_unique<mw::HTTPSessionMock>();
-
-    EXPECT_CALL(*mock_session, post(_))
-        .WillOnce(Return(std::unexpected(mw::runtimeError("Network Error"))));
-
-    OpenAiClient client("fake_key", "gpt-4o", "https://fake.endpoint.com/v1", std::move(mock_session));
-
-    std::vector<Message> history = {UserMessage{"Hi"}};
-    nlohmann::json tools = nlohmann::json::array();
-
-    auto result = client.generateResponse(history, tools).get();
-    EXPECT_FALSE(result.has_value());
-    EXPECT_EQ(mw::errorMsg(result.error()), "Network Error");
-}
diff --git a/src/main.cpp b/src/main.cpp
deleted file mode 100644
index b51feba..0000000
--- a/src/main.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-#include <cstdlib>
-#include <iostream>
-#include <memory>
-#include <string>
-
-#include <cxxopts.hpp>
-
-#include "agent.hpp"
-#include "calculator_tool.hpp"
-#include "llm_client.hpp"
-#include "memory.hpp"
-
-// A simple coroutine runner since our Task is mostly synchronous right now
-void runTask(Task<mw::E<std::string>> task)
-{
-    auto res = task.get();
-    if(res.has_value())
-    {
-        std::cout << "Agent: " << res.value() << "\n";
-    }
-    else
-    {
-        std::cout << "Agent Error: " << mw::errorMsg(res.error()) << "\n";
-    }
-}
-
-int main(int argc, char** argv)
-{
-    cxxopts::Options options("agent_smith", "C++ LLM Agent Framework");
-
-    options.add_options()
-        ("k,api-key", "LLM API Key", cxxopts::value<std::string>())
-        ("e,endpoint", "LLM API Endpoint (Base URL)", 
-            cxxopts::value<std::string>()->default_value(
-                "https://api.openai.com/v1"))
-        ("m,model", "LLM Model Name", 
-            cxxopts::value<std::string>()->default_value("gpt-4o"))
-        ("h,help", "Print usage")
-    ;
-
-    auto result = options.parse(argc, argv);
-
-    if(result.count("help"))
-    {
-        std::cout << options.help() << "\n";
-        return 0;
-    }
-
-    std::string api_key;
-    if(result.count("api-key"))
-    {
-        api_key = result["api-key"].as<std::string>();
-    }
-    else if(const char* env_key = std::getenv("OPENAI_API_KEY"))
-    {
-        api_key = env_key;
-    }
-    else
-    {
-        std::cerr << "Error: API key must be provided via --api-key or "
-                  << "OPENAI_API_KEY environment variable.\n";
-        return 1;
-    }
-
-    std::string endpoint = result["endpoint"].as<std::string>();
-    std::string model = result["model"].as<std::string>();
-
-    auto client = std::make_unique<OpenAiClient>(api_key, model, endpoint);
-    auto memory = std::make_unique<InMemoryMemory>();
-    ToolRegistry tool_registry;
-
-    auto reg_res =
-        tool_registry.registerTool(std::make_unique<CalculatorTool>());
-    if(!reg_res.has_value())
-    {
-        std::cerr << "Failed to register tool: "
-                  << mw::errorMsg(reg_res.error()) << "\n";
-        return 1;
-    }
-
-    Agent agent(std::move(client), std::move(memory), tool_registry);
-    auto allow_res = agent.allowTool("calculator");
-    if(!allow_res.has_value())
-    {
-        std::cerr << "Failed to allow tool: " << mw::errorMsg(allow_res.error())
-                  << "\n";
-        return 1;
-    }
-
-    Skill default_skill{
-        "calculator_assistant",
-        "You are a helpful assistant that can perform calculations. "
-        "Use the calculator tool when needed.",
-        {"calculator"}};
-
-    agent.activateSkill(default_skill);
-
-    std::cout << "Agent Smith initialized.\n"
-              << "Endpoint: " << endpoint << "\n"
-              << "Model: " << model << "\n"
-              << "Type 'exit' to quit.\n";
-
-    std::string user_input;
-    while(true)
-    {
-        std::cout << "You: ";
-        if(!std::getline(std::cin, user_input) || user_input == "exit")
-        {
-            break;
-        }
-
-        try
-        {
-            runTask(agent.run(user_input));
-        }
-        catch(const std::exception& e)
-        {
-            std::cerr << "Exception: " << e.what() << "\n";
-        }
-    }
-
-    return 0;
-}
diff --git a/src/memory.cpp b/src/memory.cpp
deleted file mode 100644
index bbf9419..0000000
--- a/src/memory.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "memory.hpp"
-
-void InMemoryMemory::addMessage(const Message& msg)
-{
-    history_.push_back(msg);
-}
-
-std::vector<Message> InMemoryMemory::getHistory() const
-{
-    return history_;
-}
-
-void InMemoryMemory::clear()
-{
-    history_.clear();
-}
diff --git a/src/memory.hpp b/src/memory.hpp
deleted file mode 100644
index 4d50c9b..0000000
--- a/src/memory.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include <vector>
-
-#include "message.hpp"
-
-class Memory
-{
-public:
-    virtual ~Memory() = default;
-    virtual void addMessage(const Message& msg) = 0;
-    virtual std::vector<Message> getHistory() const = 0;
-    virtual void clear() = 0;
-};
-
-class InMemoryMemory : public Memory
-{
-public:
-    void addMessage(const Message& msg) override;
-    std::vector<Message> getHistory() const override;
-    void clear() override;
-
-private:
-    std::vector<Message> history_;
-};
diff --git a/src/memory_test.cpp b/src/memory_test.cpp
deleted file mode 100644
index 25e0524..0000000
--- a/src/memory_test.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <gtest/gtest.h>
-
-#include "memory.hpp"
-
-TEST(InMemoryMemoryTest, AddAndGetHistory)
-{
-    InMemoryMemory memory;
-    memory.addMessage(SystemMessage{"sys"});
-    memory.addMessage(UserMessage{"user"});
-
-    auto history = memory.getHistory();
-    ASSERT_EQ(history.size(), 2);
-    EXPECT_TRUE(std::holds_alternative<SystemMessage>(history[0]));
-    EXPECT_TRUE(std::holds_alternative<UserMessage>(history[1]));
-}
-
-TEST(InMemoryMemoryTest, ClearHistory)
-{
-    InMemoryMemory memory;
-    memory.addMessage(UserMessage{"hi"});
-    memory.clear();
-    EXPECT_TRUE(memory.getHistory().empty());
-}
diff --git a/src/message.cpp b/src/message.cpp
deleted file mode 100644
index 7a53ff7..0000000
--- a/src/message.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "message.hpp"
-
-nlohmann::json toJson(const SystemMessage& msg)
-{
-    return {{"role", "system"}, {"content", msg.content}};
-}
-
-nlohmann::json toJson(const UserMessage& msg)
-{
-    return {{"role", "user"}, {"content", msg.content}};
-}
-
-nlohmann::json toJson(const ToolCall& msg)
-{
-    return {{"id", msg.id},
-            {"type", "function"},
-            {"function",
-             {{"name", msg.name}, {"arguments", msg.arguments.dump()}}}};
-}
-
-nlohmann::json toJson(const AssistantMessage& msg)
-{
-    nlohmann::json j = {{"role", "assistant"}};
-    if(msg.content)
-    {
-        j["content"] = *msg.content;
-    }
-    if(!msg.tool_calls.empty())
-    {
-        nlohmann::json calls_json = nlohmann::json::array();
-        for(const auto& call : msg.tool_calls)
-        {
-            calls_json.push_back(toJson(call));
-        }
-        j["tool_calls"] = calls_json;
-    }
-    return j;
-}
-
-nlohmann::json toJson(const ToolResultMessage& msg)
-{
-    return {{"role", "tool"},
-            {"tool_call_id", msg.tool_call_id},
-            {"content", msg.content}};
-}
-
-nlohmann::json toJson(const Message& msg)
-{
-    return std::visit([](const auto& m) { return toJson(m); }, msg);
-}
diff --git a/src/message.hpp b/src/message.hpp
deleted file mode 100644
index 61b1f0a..0000000
--- a/src/message.hpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-
-#include <optional>
-#include <string>
-#include <variant>
-#include <vector>
-
-#include <nlohmann/json.hpp>
-
-struct SystemMessage
-{
-    std::string content;
-};
-
-struct UserMessage
-{
-    std::string content;
-};
-
-struct ToolCall
-{
-    std::string id;
-    std::string name;
-    nlohmann::json arguments;
-};
-
-struct AssistantMessage
-{
-    std::optional<std::string> content;
-    std::vector<ToolCall> tool_calls;
-};
-
-struct ToolResultMessage
-{
-    std::string tool_call_id;
-    std::string content;
-};
-
-using Message = std::variant<SystemMessage, UserMessage, AssistantMessage,
-                             ToolResultMessage>;
-
-nlohmann::json toJson(const SystemMessage& msg);
-nlohmann::json toJson(const UserMessage& msg);
-nlohmann::json toJson(const ToolCall& msg);
-nlohmann::json toJson(const AssistantMessage& msg);
-nlohmann::json toJson(const ToolResultMessage& msg);
-nlohmann::json toJson(const Message& msg);
-
-struct Skill
-{
-    std::string name;
-    std::string system_prompt;
-    std::vector<std::string> allowed_tools;
-};
diff --git a/src/message_test.cpp b/src/message_test.cpp
deleted file mode 100644
index 54ad36e..0000000
--- a/src/message_test.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#include <gtest/gtest.h>
-
-#include "message.hpp"
-
-TEST(MessageTest, SystemMessageToJson)
-{
-    SystemMessage msg{"You are a helpful assistant."};
-    nlohmann::json j = toJson(msg);
-    EXPECT_EQ(j["role"], "system");
-    EXPECT_EQ(j["content"], "You are a helpful assistant.");
-}
-
-TEST(MessageTest, UserMessageToJson)
-{
-    UserMessage msg{"What is 2+2?"};
-    nlohmann::json j = toJson(msg);
-    EXPECT_EQ(j["role"], "user");
-    EXPECT_EQ(j["content"], "What is 2+2?");
-}
-
-TEST(MessageTest, ToolCallToJson)
-{
-    ToolCall call{"call_1", "calc", {{"a", 2}, {"b", 2}}};
-    nlohmann::json j = toJson(call);
-    EXPECT_EQ(j["id"], "call_1");
-    EXPECT_EQ(j["type"], "function");
-    EXPECT_EQ(j["function"]["name"], "calc");
-    EXPECT_EQ(j["function"]["arguments"], "{\"a\":2,\"b\":2}");
-}
-
-TEST(MessageTest, AssistantMessageToJson_ContentOnly)
-{
-    AssistantMessage msg{"The answer is 4.", {}};
-    nlohmann::json j = toJson(msg);
-    EXPECT_EQ(j["role"], "assistant");
-    EXPECT_EQ(j["content"], "The answer is 4.");
-    EXPECT_FALSE(j.contains("tool_calls"));
-}
-
-TEST(MessageTest, AssistantMessageToJson_ToolCallsOnly)
-{
-    AssistantMessage msg{std::nullopt,
-                         {{"call_1", "calc", {{"a", 2}, {"b", 2}}}}};
-    nlohmann::json j = toJson(msg);
-    EXPECT_EQ(j["role"], "assistant");
-    EXPECT_FALSE(j.contains("content"));
-    ASSERT_TRUE(j.contains("tool_calls"));
-    EXPECT_EQ(j["tool_calls"].size(), 1);
-    EXPECT_EQ(j["tool_calls"][0]["id"], "call_1");
-}
-
-TEST(MessageTest, ToolResultMessageToJson)
-{
-    ToolResultMessage msg{"call_1", "4"};
-    nlohmann::json j = toJson(msg);
-    EXPECT_EQ(j["role"], "tool");
-    EXPECT_EQ(j["tool_call_id"], "call_1");
-    EXPECT_EQ(j["content"], "4");
-}
-
-TEST(MessageTest, MessageVariantToJson)
-{
-    Message msg = UserMessage{"Hello"};
-    nlohmann::json j = toJson(msg);
-    EXPECT_EQ(j["role"], "user");
-    EXPECT_EQ(j["content"], "Hello");
-}
diff --git a/src/task.hpp b/src/task.hpp
deleted file mode 100644
index c8671a3..0000000
--- a/src/task.hpp
+++ /dev/null
@@ -1,81 +0,0 @@
-#pragma once
-
-#include <coroutine>
-#include <exception>
-#include <utility>
-
-template <typename T> class Task
-{
-public:
-    struct promise_type;
-    using handle_type = std::coroutine_handle<promise_type>;
-
-    struct promise_type
-    {
-        T value;
-        std::exception_ptr exception;
-
-        Task get_return_object()
-        {
-            return Task(handle_type::from_promise(*this));
-        }
-
-        std::suspend_never initial_suspend()
-        {
-            return {};
-        }
-        std::suspend_always final_suspend() noexcept
-        {
-            return {};
-        }
-
-        template <typename U> void return_value(U&& val)
-        {
-            value = std::forward<U>(val);
-        }
-
-        void unhandled_exception()
-        {
-            exception = std::current_exception();
-        }
-    };
-
-    Task(handle_type h) : coro(h) {}
-    Task(Task&& t) noexcept : coro(t.coro)
-    {
-        t.coro = nullptr;
-    }
-    ~Task()
-    {
-        if(coro)
-        {
-            coro.destroy();
-        }
-    }
-
-    T get()
-    {
-        if(coro.promise().exception)
-        {
-            std::rethrow_exception(coro.promise().exception);
-        }
-        return coro.promise().value;
-    }
-
-    // Awaiter to allow co_await Task<T>
-    bool await_ready() const noexcept
-    {
-        return coro.done();
-    }
-    void await_suspend(std::coroutine_handle<> awaiting_coro)
-    {
-        // Simple synchronous execution for this placeholder
-    }
-    T await_resume()
-    {
-        return get();
-    }
-
-private:
-    handle_type coro;
-};
diff --git a/src/task_test.cpp b/src/task_test.cpp
deleted file mode 100644
index 4c0fcea..0000000
--- a/src/task_test.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <stdexcept>
-#include <string>
-
-#include <gtest/gtest.h>
-
-#include "task.hpp"
-
-Task<int> asyncCompute()
-{
-    co_return 42;
-}
-
-Task<int> asyncThrow()
-{
-    throw std::runtime_error("Task Error");
-    co_return 0; // Unreachable
-}
-
-TEST(TaskTest, ReturnsValue)
-{
-    auto task = asyncCompute();
-    EXPECT_EQ(task.get(), 42);
-}
-
-TEST(TaskTest, ThrowsException)
-{
-    auto task = asyncThrow();
-    EXPECT_THROW(task.get(), std::runtime_error);
-}
diff --git a/src/tool.cpp b/src/tool.cpp
deleted file mode 100644
index 2519430..0000000
--- a/src/tool.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "tool.hpp"
-
-mw::E<void> ToolRegistry::registerTool(std::unique_ptr<Tool> tool)
-{
-    if(tools_.contains(tool->name()))
-    {
-        return std::unexpected(mw::runtimeError(
-            std::format("Tool '{}' is already registered.", tool->name())));
-    }
-    tools_[tool->name()] = std::move(tool);
-    return {};
-}
-
-mw::E<void> ToolRegistry::registerToolWithNamespace(const std::string& ns,
-                                                    std::unique_ptr<Tool> tool)
-{
-    std::string prefixed_name = std::format("{}_{}", ns, tool->name());
-    if(tools_.contains(prefixed_name))
-    {
-        return std::unexpected(mw::runtimeError(
-            std::format("Tool '{}' is already registered.", prefixed_name)));
-    }
-
-    tools_[prefixed_name] = std::move(tool);
-    return {};
-}
-
-Tool* ToolRegistry::getTool(const std::string& name) const
-{
-    auto it = tools_.find(name);
-    return it != tools_.end() ? it->second.get() : nullptr;
-}
-
-std::vector<Tool*> ToolRegistry::getAllTools() const
-{
-    std::vector<Tool*> result;
-    for(const auto& [name, tool] : tools_)
-    {
-        result.push_back(tool.get());
-    }
-    return result;
-}
diff --git a/src/tool.hpp b/src/tool.hpp
deleted file mode 100644
index 4511e29..0000000
--- a/src/tool.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-#include <format>
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include <mw/error.hpp>
-#include <nlohmann/json.hpp>
-
-#include "task.hpp"
-
-class Tool
-{
-public:
-    virtual ~Tool() = default;
-    virtual std::string name() const = 0;
-    virtual std::string description() const = 0;
-    virtual nlohmann::json parametersSchema() const = 0;
-    virtual Task<mw::E<std::string>>
-    execute(const nlohmann::json& arguments) = 0;
-};
-
-class ToolRegistry
-{
-public:
-    mw::E<void> registerTool(std::unique_ptr<Tool> tool);
-    mw::E<void> registerToolWithNamespace(const std::string& ns,
-                                          std::unique_ptr<Tool> tool);
-    Tool* getTool(const std::string& name) const;
-    std::vector<Tool*> getAllTools() const;
-
-private:
-    std::unordered_map<std::string, std::unique_ptr<Tool>> tools_;
-};
diff --git a/src/tool_test.cpp b/src/tool_test.cpp
deleted file mode 100644
index f6f938a..0000000
--- a/src/tool_test.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#include <gtest/gtest.h>
-#include <nlohmann/json.hpp>
-
-#include "tool.hpp"
-
-class MockTool : public Tool
-{
-public:
-    std::string name() const override
-    {
-        return "mock_tool";
-    }
-    std::string description() const override
-    {
-        return "Mock Tool";
-    }
-    nlohmann::json parametersSchema() const override
-    {
-        return nlohmann::json::object();
-    }
-    Task<mw::E<std::string>> execute(const nlohmann::json&) override
-    {
-        co_return "mock_result";
-    }
-};
-
-TEST(ToolRegistryTest, RegisterAndGetTool)
-{
-    ToolRegistry registry;
-    auto res = registry.registerTool(std::make_unique<MockTool>());
-    ASSERT_TRUE(res.has_value());
-
-    Tool* tool = registry.getTool("mock_tool");
-    ASSERT_NE(tool, nullptr);
-    EXPECT_EQ(tool->name(), "mock_tool");
-}
-
-TEST(ToolRegistryTest, DuplicateRegistrationFails)
-{
-    ToolRegistry registry;
-    ASSERT_TRUE(
-        registry.registerTool(std::make_unique<MockTool>()).has_value());
-    EXPECT_FALSE(
-        registry.registerTool(std::make_unique<MockTool>()).has_value());
-}
-
-TEST(ToolRegistryTest, RegisterWithNamespace)
-{
-    ToolRegistry registry;
-    auto res =
-        registry.registerToolWithNamespace("ns", std::make_unique<MockTool>());
-    ASSERT_TRUE(res.has_value());
-
-    Tool* tool = registry.getTool("ns_mock_tool");
-    ASSERT_NE(tool, nullptr);
-    EXPECT_EQ(tool->name(), "mock_tool");
-}
-
-TEST(ToolRegistryTest, GetAllTools)
-{
-    ToolRegistry registry;
-    registry.registerTool(std::make_unique<MockTool>());
-
-    auto tools = registry.getAllTools();
-    ASSERT_EQ(tools.size(), 1);
-    EXPECT_EQ(tools[0]->name(), "mock_tool");
-}