> ## 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.

# Custom Installer Playbook

> Ship the Example Agent pre-loaded in a branded GAIA installer. Three-OS walkthrough.

<Info>
  **Source code:**
  [`src/gaia/apps/webui/services/agent-seeder.cjs`](https://github.com/amd/gaia/blob/main/src/gaia/apps/webui/services/agent-seeder.cjs) ·
  [`src/gaia/installer/export_import.py`](https://github.com/amd/gaia/blob/main/src/gaia/installer/export_import.py) ·
  [`src/gaia/apps/webui/electron-builder.yml`](https://github.com/amd/gaia/blob/main/src/gaia/apps/webui/electron-builder.yml)
</Info>

**Time to complete:** 45–75 minutes
**What you'll build:** A branded GAIA installer for Windows, macOS, or Ubuntu with the **Example Agent** preloaded
**What you'll learn:** How bundled agents flow from a staging directory through `electron-builder` into the first-launch seeder, plus how to share agents between existing GAIA installations without rebuilding an installer

***

## What's different about this playbook

This playbook is the end-to-end walkthrough for shipping a branded GAIA installer with your agent preloaded — useful when `pip install amd-gaia` or enterprise silent-install isn't the right fit. Take a working agent, drop it into the staging directory, run one `npm` command per OS, install the binary, and watch the seeder surface your agent in the Agent UI on first launch.

Two paths are covered:

* **Path A — Branded installer.** You build and ship a full GAIA installer with your agent preloaded. This is what OEM partners, enterprise teams, and community builders typically want.
* **Path B — Share an existing agent.** You already have GAIA installed on both sides and just want to move an agent between machines. No installer build.

***

## Path A — Branded installer

The running example is the **Example Agent** — the same minimal Python agent that ships preloaded in the stock GAIA installer.

<Steps>
  <Step title="Prerequisites">
    Who this path is for: **OEM partners** pre-loading GAIA on Ryzen AI hardware, **enterprise teams** distributing an internal-knowledge agent, and **community builders** sharing a branded specialty agent.

    What you need installed:

    * Git
    * Node.js 18+ and npm
    * Python 3.10+ (for running the agent locally to verify it before packaging)

    Clone and install:

    ```bash theme={null}
    git clone https://github.com/amd/gaia.git
    cd gaia/src/gaia/apps/webui
    npm install
    ```

    All subsequent steps assume your working directory is `gaia/src/gaia/apps/webui/`.
  </Step>

  <Step title="Create the Example Agent">
    Create the bundled-agent staging directory and drop in a Python `agent.py`:

    ```bash theme={null}
    mkdir -p build/bundled-agents/example-agent
    ```

    Create `build/bundled-agents/example-agent/agent.py`:

    ```python title="build/bundled-agents/example-agent/agent.py" theme={null}
    # Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
    # SPDX-License-Identifier: MIT

    from gaia.agents.base.agent import Agent
    from gaia.agents.base.console import AgentConsole


    class ExampleAgent(Agent):
        AGENT_ID = "example-agent"
        AGENT_NAME = "Example Agent"
        AGENT_DESCRIPTION = (
            "A bundled example agent that shows how installer-seeded custom agents work"
        )
        CONVERSATION_STARTERS = [
            "What are you an example of?",
            "How do I build my own agent like you?",
        ]

        def _get_system_prompt(self) -> str:
            return (
                "You are GAIA's bundled Example Agent — a working demonstration of a "
                "custom agent seeded by the installer. Explain plainly that you exist "
                "to show how custom agents are packaged and loaded, and point anyone "
                "who wants to build their own to "
                "https://amd-gaia.ai/docs/guides/custom-agent."
            )

        def _create_console(self) -> AgentConsole:
            return AgentConsole()

        def _register_tools(self) -> None:
            pass
    ```

    **Why this location matters.** The `build/bundled-agents/` directory is the build-time staging area picked up by the `extraResources` entry in `electron-builder.yml`:

    ```yaml theme={null}
    extraResources:
      - from: build/bundled-agents
        to: agents
        filter: ["**/*"]
    ```

    At install time the contents end up under `process.resourcesPath/agents/<agent-id>/` inside the installed app. On first launch, `seedBundledAgents()` in [`src/gaia/apps/webui/services/agent-seeder.cjs`](https://github.com/amd/gaia/blob/main/src/gaia/apps/webui/services/agent-seeder.cjs) copies them into `~/.gaia/agents/<agent-id>/`, writes a `.seeded` sentinel inside the agent directory, and records a marker at `~/.gaia/seeder/<agent-id>.seeded`. The marker is what makes seeding one-time-per-machine: as long as it exists the agent is never seeded again — even if the user deletes the agent directory. Deleting a seeded agent is honored permanently.

    <Warning>
      **Agent code runs with user privileges.** The `agent.py` file you bundle executes when the user selects your agent. Only bundle code you wrote or have audited.
    </Warning>
  </Step>

  <Step title="Build the installer">
    Pick your target platform. Each command builds the full GAIA Agent UI installer with your Example Agent baked in.

    <Tabs>
      <Tab title="Windows">
        ```bash theme={null}
        npm run package:win
        ```

        Output:

        ```
        dist-app/gaia-agent-ui-<version>-x64-setup.exe
        ```
      </Tab>

      <Tab title="macOS">
        ```bash theme={null}
        npm run package:mac
        ```

        Output:

        ```
        dist-app/gaia-agent-ui-<version>-arm64.dmg
        ```
      </Tab>

      <Tab title="Ubuntu">
        ```bash theme={null}
        npm run package:linux
        ```

        Output:

        ```
        dist-app/gaia-agent-ui-<version>-amd64.deb
        ```
      </Tab>
    </Tabs>

    <Note>
      Cross-compilation is not supported end-to-end today. Build each target on its native OS (or in a matching VM / CI runner).
    </Note>
  </Step>

  <Step title="Install and verify">
    <Tabs>
      <Tab title="Windows">
        1. Double-click the `.exe` in `dist-app/`.
        2. Accept the NSIS prompts through to completion.
        3. Launch **GAIA** from the Start Menu.
      </Tab>

      <Tab title="macOS">
        1. Open the `.dmg` in `dist-app/`.
        2. Drag **GAIA** to `Applications`.
        3. Launch from Launchpad or `Applications/`.
      </Tab>

      <Tab title="Ubuntu">
        ```bash theme={null}
        sudo apt install ./dist-app/gaia-agent-ui-<version>-amd64.deb
        ```

        Launch from your desktop environment's application menu, or run `gaia-agent-ui` from a terminal.
      </Tab>
    </Tabs>

    **Verify the seeder ran:**

    1. Open the Agent UI. On first launch, `seedBundledAgents()` copies every directory under `<resources>/agents/` into `~/.gaia/agents/`, writing a `.seeded` sentinel in each agent directory and a per-agent marker under `~/.gaia/seeder/` so each agent is seeded at most once per machine.
    2. Open the agent dropdown in the UI header — **Example Agent** should appear alongside the built-in agents.
    3. Select **Example Agent** and send "What are you an example of?". It should introduce itself as the bundled example and point you at the custom-agent guide.

    If the agent does not appear:

    * Confirm `~/.gaia/agents/example-agent/agent.py` exists on the target machine.
    * Confirm `~/.gaia/agents/example-agent/.seeded` exists — if it's missing, the seeder did not run; check the Electron main-process logs and `~/.gaia/logs/seeder.log`.
    * To force a fresh seed (for example after a bad or incomplete copy), delete **both** `~/.gaia/agents/example-agent/` and the marker `~/.gaia/seeder/example-agent.seeded`, then relaunch. Deleting the agent directory alone will NOT re-seed — the surviving marker means "the user deleted this agent" and the seeder honors that permanently.
  </Step>

  <Step title="(Optional) Branding">
    Most users ship with the default GAIA branding and only customize the agent. If you want a branded installer, edit [`src/gaia/apps/webui/electron-builder.yml`](https://github.com/amd/gaia/blob/main/src/gaia/apps/webui/electron-builder.yml) before re-running the `package:*` command:

    * `productName` → user-facing app name (e.g., `Acme GAIA`)
    * `appId` → your reverse-DNS namespace (e.g., `com.acme.gaia`)

    Icons, sidebar bitmaps, and installer graphics are referenced by path inside the same file — replace the assets in place.

    **Signing is out of scope for this playbook.** An unsigned or ad-hoc-signed installer is perfectly usable for internal distribution and testing. For production signing (Windows Authenticode, macOS Developer ID + notarization), see the [Code Signing Reference](/docs/deployment/code-signing).
  </Step>
</Steps>

***

## Path B — Share an existing agent

If you already have GAIA installed and want to move an agent to another machine — or share it with a teammate — you don't need to build an installer. Use the agent bundle export/import flow instead.

The bundle is a `.zip` containing your custom agents plus a `bundle.json` table of contents. Export on the source machine, import on the destination.

### Export

<CodeGroup>
  ```bash CLI theme={null}
  gaia agent export
  # → creates ~/.gaia/export.zip containing every agent under ~/.gaia/agents/
  ```

  ```text UI theme={null}
  Settings → Custom Agents → Export All
  # Saves the bundle via a native file-picker dialog.
  ```
</CodeGroup>

Under the hood both flows call `export_custom_agents()` in [`src/gaia/installer/export_import.py`](https://github.com/amd/gaia/blob/main/src/gaia/installer/export_import.py), which walks `~/.gaia/agents/` and writes a deterministic zip with a `bundle.json` manifest.

### Import

<CodeGroup>
  ```bash CLI theme={null}
  gaia agent import ~/Downloads/gaia-agents-export.zip
  # Prompts for trust confirmation before installing.
  ```

  ```text UI theme={null}
  Settings → Custom Agents → Import
  # File picker → trust confirmation → done.
  ```
</CodeGroup>

Imports go through `import_agent_bundle()` in [`src/gaia/installer/export_import.py`](https://github.com/amd/gaia/blob/main/src/gaia/installer/export_import.py). Each agent is staged in a temp directory and atomically moved into `~/.gaia/agents/<id>/`, so a partial failure leaves previously-installed agents intact. Zip entries are validated for path traversal, absolute paths, symlinks, size, and entry count before anything touches disk.

<Warning>
  **Importing a bundle installs third-party Python code that runs on your machine when the agent is selected.** Only import bundles from sources you trust. The UI import flow shows the list of agent IDs in the bundle and requires an explicit confirmation click before extraction.
</Warning>

### When to use which path

| Scenario                                                   | Path                       |
| ---------------------------------------------------------- | -------------------------- |
| Shipping GAIA + your agent to users who don't have GAIA    | Path A — Branded installer |
| Moving an agent between two machines that already run GAIA | Path B — Export/Import     |
| Publishing an agent for the community to drop in           | Path B (share the `.zip`)  |
| OEM pre-install on Ryzen AI hardware                       | Path A                     |

***

## Next steps

<CardGroup cols={3}>
  <Card title="Custom Agents" icon="wand-magic-sparkles" href="/docs/guides/custom-agent">
    Deep reference for agent authoring, manifest schema, tools, and MCP.
  </Card>

  <Card title="Code Signing" icon="signature" href="/docs/deployment/code-signing">
    Per-platform signing secrets, CI integration, troubleshooting.
  </Card>

  <Card title="Agent UI" icon="desktop" href="/docs/deployment/ui">
    Desktop shell architecture, build pipeline, Electron integration.
  </Card>
</CardGroup>
