> ## Documentation Index
> Fetch the complete documentation index at: https://amd-gaia.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration Guide

> Add AI agent capabilities to any C++ project — three lines of CMake, zero manual dependencies

<Info>
  **Source Code:** [`cpp/CMakeLists.txt`](https://github.com/amd/gaia/blob/main/cpp/CMakeLists.txt) -- build configuration with install rules, export targets, and FetchContent support.
</Info>

<Note>
  **Prerequisites:** Familiarity with CMake and C++17. See the [C++ Framework Overview](/docs/cpp/overview) for build instructions and the `AgentConfig` reference.
</Note>

***

## Overview

`gaia_core` is designed to drop into any C++ project with minimal friction. The library is self-contained — all dependencies (nlohmann/json, cpp-httplib) are resolved automatically, so you never install or manage them by hand. Your project only needs **CMake 3.14+** and a **C++17 compiler**.

**The shortest path** — add three lines to your `CMakeLists.txt`:

```cmake theme={null}
FetchContent_Declare(gaia GIT_REPOSITORY https://github.com/amd/gaia.git GIT_TAG main SOURCE_SUBDIR cpp)
FetchContent_MakeAvailable(gaia)
target_link_libraries(my_app PRIVATE gaia::gaia_core)
```

That gives you `#include <gaia/agent.h>`, the full agent loop, tool registry, MCP client, and JSON utilities — no manual installs, no system packages, no dependency conflicts.

### Integration Methods

| Method             | When to use                                                            |
| ------------------ | ---------------------------------------------------------------------- |
| **FetchContent**   | Default choice -- no install step, works everywhere                    |
| **Git submodule**  | You want the source in your repo for offline builds or pinned versions |
| **find\_package**  | You want a system-wide install or use a package manager                |
| **Shared library** | You need a `.so` / `.dll` for plugin architectures                     |

***

<Tabs>
  <Tab title="FetchContent (Recommended)">
    The simplest approach -- CMake downloads and builds `gaia_core` as part of your project. No install step, no system packages, no manual dependency management.

    ```cmake title="CMakeLists.txt" theme={null}
    cmake_minimum_required(VERSION 3.14)
    project(my_agent LANGUAGES CXX)

    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)

    include(FetchContent)
    FetchContent_Declare(
        gaia
        GIT_REPOSITORY https://github.com/amd/gaia.git
        GIT_TAG        main
        SOURCE_SUBDIR  cpp
    )
    FetchContent_MakeAvailable(gaia)

    add_executable(my_agent main.cpp)
    target_link_libraries(my_agent PRIVATE gaia::gaia_core)
    ```

    <Note>
      `SOURCE_SUBDIR cpp` tells CMake to use only the `cpp/` subdirectory of the GAIA repository. Your build tree contains only the C++ library and its dependencies.
    </Note>

    <Note>
      When consumed as a sub-project, `GAIA_BUILD_TESTS` and `GAIA_BUILD_EXAMPLES` default to `OFF`, so you only get the library -- no test binaries or demo executables in your build tree.
    </Note>

    **That is it.** All transitive dependencies (nlohmann/json, cpp-httplib) are fetched automatically. Your `main.cpp` can `#include <gaia/agent.h>` and subclass `gaia::Agent` immediately.
  </Tab>

  <Tab title="Git Submodule">
    Use this when you want the GAIA source checked into your repository for offline/reproducible builds or to pin a specific commit.

    ```bash theme={null}
    # Add GAIA as a submodule
    git submodule add https://github.com/amd/gaia.git extern/gaia
    git submodule update --init
    ```

    Then in your `CMakeLists.txt`, add the `cpp/` subdirectory:

    ```cmake title="CMakeLists.txt" theme={null}
    cmake_minimum_required(VERSION 3.14)
    project(my_agent LANGUAGES CXX)

    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)

    add_subdirectory(extern/gaia/cpp)

    add_executable(my_agent main.cpp)
    target_link_libraries(my_agent PRIVATE gaia::gaia_core)
    ```

    <Note>
      This works identically to FetchContent but with the source already in your tree. `GAIA_BUILD_TESTS` and `GAIA_BUILD_EXAMPLES` default to `OFF` because `gaia-cpp` is not the top-level project. To update, run `git submodule update --remote extern/gaia`.
    </Note>
  </Tab>

  <Tab title="find_package (Install)">
    Use this method when you want to install `gaia_core` once and consume it from multiple projects, or when you manage dependencies via a system package manager.

    <Steps>
      <Step title="Install nlohmann/json">
        `nlohmann/json` is a public dependency of `gaia_core` (JSON types appear in the API). Install it before building:

        <Tabs>
          <Tab title="apt (Debian/Ubuntu)">
            ```bash theme={null}
            sudo apt install nlohmann-json3-dev
            ```
          </Tab>

          <Tab title="vcpkg">
            ```bash theme={null}
            vcpkg install nlohmann-json
            ```
          </Tab>

          <Tab title="conan">
            ```bash theme={null}
            conan install nlohmann_json/3.11.3
            ```
          </Tab>
        </Tabs>
      </Step>

      <Step title="Build and install gaia_core">
        ```bash theme={null}
        cmake -B build -S cpp -DCMAKE_BUILD_TYPE=Release
        ```

        ```bash theme={null}
        cmake --build build --config Release
        ```

        ```bash theme={null}
        cmake --install build --prefix /usr/local
        ```

        On Windows with MSVC, specify the install prefix explicitly:

        ```bat theme={null}
        cmake --install build --prefix C:\gaia_core --config Release
        ```
      </Step>

      <Step title="Consume in your project">
        ```cmake title="CMakeLists.txt" theme={null}
        cmake_minimum_required(VERSION 3.14)
        project(my_agent LANGUAGES CXX)

        set(CMAKE_CXX_STANDARD 17)
        set(CMAKE_CXX_STANDARD_REQUIRED ON)

        find_package(gaia_core REQUIRED)

        add_executable(my_agent main.cpp)
        target_link_libraries(my_agent PRIVATE gaia::gaia_core)
        ```

        If you installed to a non-standard prefix, pass it at configure time:

        ```bash theme={null}
        cmake -B build -DCMAKE_PREFIX_PATH=/usr/local
        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="Shared Library (DLL)">
    Build `gaia_core` as a shared library for plugin architectures or language bindings:

    ```bash theme={null}
    cmake -B build -S cpp -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release
    ```

    ```bash theme={null}
    cmake --build build --config Release
    ```

    This produces:

    * **Linux:** `libgaia_core.so`
    * **Windows:** `gaia_core.dll` + `gaia_core.lib` (import library)

    <Warning>
      **STL types in the public API.** `std::string`, `std::vector`, `std::function`, and `std::map` appear in the `gaia_core` public headers. On MSVC, the DLL and **all consumers** must be built with the **same compiler version and CRT runtime** (`/MD` or `/MT`). Mixing runtimes or compiler versions across the DLL boundary causes crashes and undefined behavior. Use the same toolchain (Visual Studio version, platform toolset, runtime library setting) for both the DLL and your consumer project.
    </Warning>

    Consumer `CMakeLists.txt` is identical to the `find_package` method -- the installed config handles shared vs. static automatically.
  </Tab>
</Tabs>

***

## Subclassing Example

Here is a complete minimal agent that registers one tool and processes a query. This works with any of the three integration methods above.

```cpp title="time_agent.cpp" theme={null}
#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

#include <gaia/agent.h>
#include <gaia/types.h>

/// A minimal custom agent with one tool.
class TimeAgent : public gaia::Agent {
public:
    TimeAgent() : Agent(makeConfig()) {
        init();  // triggers registerTools() and composes system prompt
    }

protected:
    std::string getSystemPrompt() const override {
        return "You are a helpful assistant that can tell the current time. "
               "Use the get_current_time tool when the user asks about the time.";
    }

    void registerTools() override {
        toolRegistry().registerTool(
            "get_current_time",
            "Return the current local date and time as an ISO 8601 string.",
            [](const gaia::json& /*args*/) -> gaia::json {
                auto now = std::chrono::system_clock::now();
                auto time = std::chrono::system_clock::to_time_t(now);
                std::tm tm_buf{};
#ifdef _WIN32
                localtime_s(&tm_buf, &time);
#else
                localtime_r(&time, &tm_buf);
#endif
                std::ostringstream oss;
                oss << std::put_time(&tm_buf, "%Y-%m-%dT%H:%M:%S");
                return {{"current_time", oss.str()}};
            },
            {
                // This tool takes no parameters, but you could add them:
                // {"timezone", gaia::ToolParamType::STRING, false, "IANA timezone"}
            }
        );
    }

private:
    static gaia::AgentConfig makeConfig() {
        gaia::AgentConfig cfg;
        cfg.baseUrl = "http://localhost:13305/api/v1";
        cfg.modelId = "Qwen3-4B-GGUF";
        cfg.maxSteps = 10;
        return cfg;
    }
};

int main() {
    try {
        TimeAgent agent;
        auto result = agent.processQuery("What time is it right now?");

        if (result.contains("result")) {
            std::cout << result["result"].get<std::string>() << std::endl;
        }
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}
```

Add it to your `CMakeLists.txt`:

```cmake theme={null}
add_executable(time_agent time_agent.cpp)
target_link_libraries(time_agent PRIVATE gaia::gaia_core)
```

***

## Using Alternative LLM Backends

The GAIA C++ agent framework is **not tied to [Lemonade](https://lemonade-server.ai) or any specific LLM provider**. It talks to a standard HTTP endpoint — any server that implements the OpenAI chat completions API works out of the box. Switch backends by changing two fields:

```cpp theme={null}
gaia::AgentConfig cfg;
cfg.baseUrl = "http://localhost:8080/v1";   // your server's base URL
cfg.modelId = "my-model-name";              // model name your server expects
```

### What "OpenAI-Compatible" Means

The agent uses a single HTTP endpoint: `POST {baseUrl}/chat/completions`. It sends a standard request body and expects a standard response:

```json theme={null}
// Request (what the agent sends)
{
  "model": "...",          // from AgentConfig::modelId
  "messages": [...],       // system prompt + conversation history
  "temperature": 0.7
}

// Response (what the agent expects)
{
  "choices": [{
    "message": { "content": "..." }
  }]
}
```

That is the entire API surface. No embeddings endpoint, no streaming (unless `cfg.streaming = true`), no fine-tuning API. Any server that handles this request/response format works — local or remote, open-source or commercial.

### Local Inference Servers

<Tabs>
  <Tab title="llama.cpp">
    [llama.cpp](https://github.com/ggerganov/llama.cpp) includes a built-in server with OpenAI-compatible endpoints. This is the most direct way to run a GGUF model locally without any Python dependencies.

    ```bash theme={null}
    # Download a model and start the server
    ./llama-server -m qwen3-4b.gguf --port 8080
    ```

    ```cpp theme={null}
    gaia::AgentConfig cfg;
    cfg.baseUrl = "http://localhost:8080/v1";
    cfg.modelId = "qwen3-4b.gguf";  // llama.cpp ignores this field, but it must be non-empty
    ```

    <Note>
      llama.cpp runs entirely in C++ — no Python, no pip. If you want a fully native stack (C++ agent + C++ inference), this is the combination to use.
    </Note>
  </Tab>

  <Tab title="Ollama">
    [Ollama](https://ollama.com/) provides an OpenAI-compatible API on port 11434 with simple model management.

    ```bash theme={null}
    # Pull a model and start Ollama
    ollama pull qwen3:4b
    ollama serve
    ```

    ```cpp theme={null}
    gaia::AgentConfig cfg;
    cfg.baseUrl = "http://localhost:11434/v1";
    cfg.modelId = "qwen3:4b";
    ```
  </Tab>

  <Tab title="vLLM">
    [vLLM](https://github.com/vllm-project/vllm) serves models with OpenAI-compatible API and optimized batching for high throughput.

    ```bash theme={null}
    python -m vllm.entrypoints.openai.api_server \
        --model Qwen/Qwen3-4B --port 8000
    ```

    ```cpp theme={null}
    gaia::AgentConfig cfg;
    cfg.baseUrl = "http://localhost:13305/v1";
    cfg.modelId = "Qwen/Qwen3-4B";
    ```
  </Tab>

  <Tab title="Lemonade (default)">
    [Lemonade Server](https://lemonade-server.ai) is the default backend, optimized for AMD Ryzen AI NPU and GPU acceleration.

    ```bash theme={null}
    lemonade-server serve
    ```

    ```cpp theme={null}
    gaia::AgentConfig cfg;
    // defaults work out of the box
    cfg.baseUrl = "http://localhost:13305/api/v1";
    cfg.modelId = "Qwen3-4B-GGUF";
    ```
  </Tab>
</Tabs>

### Cloud and Remote Providers

You can also point the agent at cloud-hosted LLM services. GAIA auto-detects
OpenSSL at configure time (`find_package(OpenSSL QUIET)`); if it is installed,
HTTPS support is compiled in automatically — no extra flags needed:

```bash theme={null}
cmake -B build -S cpp
```

If OpenSSL isn't found, the build still succeeds but falls back to HTTP only.

<Tabs>
  <Tab title="OpenAI">
    ```cpp theme={null}
    gaia::AgentConfig cfg;
    cfg.baseUrl = "https://api.openai.com/v1";
    cfg.modelId = "gpt-4o";
    ```

    Set the `Authorization` header via the `OPENAI_API_KEY` environment variable, or modify the HTTP request in a custom `Agent` subclass.
  </Tab>

  <Tab title="Azure OpenAI">
    ```cpp theme={null}
    gaia::AgentConfig cfg;
    cfg.baseUrl = "https://YOUR_RESOURCE.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT";
    cfg.modelId = "gpt-4o";
    ```
  </Tab>

  <Tab title="Any OpenAI-compatible API">
    Any hosted service that exposes a `/chat/completions` endpoint works:

    ```cpp theme={null}
    gaia::AgentConfig cfg;
    cfg.baseUrl = "https://your-server.example.com/v1";
    cfg.modelId = "your-model-name";
    ```
  </Tab>
</Tabs>

<Note>
  **Model requirements:** The agent needs a model that can produce structured JSON output with tool names and arguments. Most instruction-tuned models 4B+ work well. Smaller models (\< 3B parameters) may struggle with the structured response format required for tool calling.
</Note>

***

## DLL Export Macros

All public classes and functions in `gaia_core` are annotated with the `GAIA_API` macro, which is generated automatically by CMake's `GenerateExportHeader`. When building as a shared library:

* **Windows (MSVC):** `GAIA_API` expands to `__declspec(dllexport)` when building the library, and `__declspec(dllimport)` when consuming it.
* **Linux:** `GAIA_API` expands to `__attribute__((visibility("default")))`.
* **Static library:** `GAIA_API` expands to nothing.

No manual annotation is needed in consumer code. Linking against the `gaia::gaia_core` CMake target sets all required compile definitions automatically.

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="FetchContent is slow on first build">
    The first configure downloads nlohmann/json, cpp-httplib, and (if tests are on) Google Test from GitHub. Subsequent builds use the CMake cache. To speed up repeated clean builds, consider using a local clone or a CMake dependency cache.
  </Accordion>

  <Accordion title="find_package cannot find gaia_core">
    Ensure you ran `cmake --install` and that the install prefix is in your `CMAKE_PREFIX_PATH`:

    ```bash theme={null}
    cmake -B build -DCMAKE_PREFIX_PATH=/path/to/gaia_core/install
    ```
  </Accordion>

  <Accordion title="Linker errors with nlohmann/json on find_package">
    `nlohmann/json` is a public dependency. When using `find_package(gaia_core)`, the installed config file calls `find_dependency(nlohmann_json)`. Make sure nlohmann/json is installed system-wide (see the install steps above).
  </Accordion>

  <Accordion title="DLL crashes on Windows">
    Verify that your consumer project uses the same MSVC version, platform toolset, and CRT runtime (`/MD` vs `/MT`) as the `gaia_core` DLL. Mismatched runtimes corrupt the heap when STL objects cross the DLL boundary.
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="C++ Framework Overview" icon="code" href="/docs/cpp/overview">
    Prerequisites, AgentConfig reference, and the full project structure
  </Card>

  <Card title="C++ Source Code" icon="github" href="https://github.com/amd/gaia/tree/main/cpp">
    Browse the implementation on GitHub
  </Card>

  <Card title="Customizing Your Agent" icon="sliders" href="/docs/cpp/custom-agent">
    Custom prompts, typed tools, MCP servers, output capture, and AgentConfig tuning
  </Card>

  <Card title="Wi-Fi Troubleshooter Agent" icon="wifi" href="/docs/cpp/wifi-agent">
    Full network diagnostic and auto-fix using registered C++ tools
  </Card>

  <Card title="MCP Client" icon="plug" href="/docs/sdk/sdks/mcp">
    How MCP client-server integration works in GAIA
  </Card>
</CardGroup>

***

<small style="color: #666;">
  **License**

  Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.

  SPDX-License-Identifier: MIT
</small>
