> For the complete documentation index, see [llms.txt](https://docs.euno.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.euno.ai/setup-configuration/account-settings/local-agents.md).

# Local Agents

A local agent lets Euno run supported source-integration network requests from your environment without opening inbound firewall ports. The agent connects **outbound** to Euno's relay, and Euno routes the selected source's traffic through the agent's encrypted tunnel.

{% hint style="info" %}
Local agents are currently supported for **MySQL**, **SQL Server**, **Azure Data Factory**, **Power BI**, and **Snowflake** integrations.
{% endhint %}

## Step 1: Create a local agent in Euno

1. Navigate to **Account Settings → Local Agents**.
2. Click **+ Create agent**.
3. Enter a **name** for the agent (e.g. `my-private-network-agent`) and optionally a **description** (e.g. `Production network - US East`).
4. Save. On the confirmation screen, copy the **Agent ID** and **Agent Secret**.

{% hint style="warning" %}
The Agent Secret is shown only once. Store it securely before closing the dialog — it cannot be retrieved afterwards.
{% endhint %}

## Step 2: Deploy the agent container

### Quick test

```bash
docker run -d --restart unless-stopped \
  -e AGENT_ID=<your-agent-id> \
  -e AGENT_SECRET=<your-agent-secret> \
  eunoai/euno-local-agent:v1.0.0
```

### Persistent setup (recommended)

Create a `docker-compose.yml` file on a machine that can reach the required private services, secret stores, or external APIs:

```yaml
services:
  euno-local-agent:
    image: eunoai/euno-local-agent:v1.0.0
    environment:
      AGENT_ID: <your-agent-id>
      AGENT_SECRET: <your-agent-secret>
    restart: unless-stopped
```

Then start the agent:

```bash
docker compose up -d
```

### Environment variables

| Variable       | Required | Description                              |
| -------------- | -------- | ---------------------------------------- |
| `AGENT_ID`     | Yes      | Agent UUID from the Euno Local Agents UI |
| `AGENT_SECRET` | Yes      | Secret from agent creation (shown once)  |

## Choosing an agent version

Euno publishes an immutable tag for every supported agent release, such as `v1.0.0`. Deploy a specific version rather than `:latest`, so that recreating the container or pulling again never changes the agent version underneath you. This matters because the agent runs inside your network and can reach private services and secret stores.

Available releases are listed on the [agent's Docker Hub tags page](https://hub.docker.com/r/eunoai/euno-local-agent/tags). Most entries there are not releases: a 40-character Git SHA is an internal development build, and a `sha256-….sig` entry is a signature rather than an image. Only the `vMAJOR.MINOR.PATCH` tags are supported for customer deployments.

Version numbers follow `vMAJOR.MINOR.PATCH`. A patch release carries fixes and maintenance only. A minor release adds backwards-compatible capabilities. A major release changes how the agent is deployed or configured, or removes a capability, so read the release notes before taking one.

{% hint style="info" %}
The `:latest` tag usually points at the newest release, but it is not guaranteed to. A fix released onto an older version line keeps its own version and leaves `:latest` alone, and a release can also be published deliberately without moving `:latest`. It is convenient for evaluation, but a pinned version or digest is the supported way to run the agent in production.
{% endhint %}

### Check which version you are running

```bash
# the image reference the container was started from
docker inspect --format '{{.Config.Image}}' <container-name>
# the exact digest that reference resolved to
docker image inspect --format '{{index .RepoDigests 0}}' eunoai/euno-local-agent:v1.0.0
```

To confirm which release a digest belongs to, inspect the version tag and compare the `Digest:` line:

```bash
docker buildx imagetools inspect eunoai/euno-local-agent:v1.0.0
```

### Upgrade

Upgrades are deliberate: change the version in your `docker-compose.yml`, then recreate the container.

```bash
docker compose pull
docker compose up -d
```

Check the release you are moving to, confirm the agent reconnects on the **Account Settings → Local Agents** page, and re-run a source sync to validate.

### Roll back

Set the previous version in `docker-compose.yml` and run the same two commands. Because release tags are immutable, a rollback always returns you to exactly the image you ran before.

## Verifying the agent image (recommended)

Euno publishes the agent image signed, so you can confirm you are running exactly the image Euno built.

The strongest form of pinning combines the release version with its digest. The version records which supported release you chose; the digest guarantees the content cannot change.

```bash
# read the Digest: line for the release you are deploying
docker buildx imagetools inspect eunoai/euno-local-agent:v1.0.0
# then reference version and digest together in your compose/run
#   image: eunoai/euno-local-agent:v1.0.0@sha256:<digest>
```

Docker verifies the digest on every pull, so a reference in this form always resolves to the same image.

Save Euno's public signing key as `euno-agent.pub`:

```
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtC8el1SduKyqU7Dgcc2crmhHkubI
H1gAS7PcerXGYgfgV98B3n9S1QPhGWOxEovBSChyV/+YNfAzTBUaagnn1A==
-----END PUBLIC KEY-----
```

Then verify the signature against it:

```bash
cosign verify --key euno-agent.pub \
  eunoai/euno-local-agent@sha256:<digest>
```

A successful verification confirms the image was signed by Euno's key and has not been altered.

## Step 3: Verify the connection

1. Go back to **Account Settings → Local Agents** and click **Refresh**.
2. The agent's status should change from **Disconnected** to **Connected**.

You can also verify by checking the container logs:

```bash
docker logs <container-name>
# Expected: agent <uuid> connected to relay
```

## Step 4: Configure a source to use the agent

When creating or editing a supported source, expand the **Advanced** section and select your agent from the **Local agent** dropdown. The **Need a local agent?** link under the credential fields also opens this section.

* For **MySQL** and **SQL Server**, set the hostname to the database address that the agent can reach. Euno routes the database connection through the agent.
* For **Azure Data Factory**, Euno routes both the Microsoft Entra token request and Azure Resource Manager metadata requests through the agent. If you select a client-secret handle, the agent also resolves that handle. You can still enter the client secret directly.
* For **Power BI**, Euno routes Microsoft Entra, Power BI, Fabric, optional Microsoft Graph, and Fabric Lakehouse SQL traffic through the agent.
* For **Snowflake**, Euno routes connector HTTPS traffic, including authentication, queries, OCSP checks, and result downloads, through the agent.

Click **Test & Save**. Euno will validate the connection through the agent before saving.

The selected agent is authoritative for the source. If the agent is unavailable or cannot reach a required endpoint, validation and sync fail instead of retrying directly from Euno.

| Source                 | Traffic routed through the agent                                                                                                                                                                             |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **MySQL**              | MySQL protocol traffic to the configured database host and port.                                                                                                                                             |
| **SQL Server**         | TDS traffic to the configured database host and port.                                                                                                                                                        |
| **Azure Data Factory** | Microsoft Entra token and Azure Resource Manager metadata requests.                                                                                                                                          |
| **Power BI**           | Microsoft Entra token requests, Power BI and Fabric REST APIs, optional Microsoft Graph requests, and Fabric Lakehouse SQL endpoint traffic. DNS resolution for those targets occurs from the agent network. |
| **Snowflake**          | Snowflake connector HTTPS traffic, including authentication, queries, OCSP checks, and result downloads. DNS resolution for those targets occurs from the agent network.                                     |

The local agent tunnels TCP traffic. It does not proxy UDP-based protocols.

## Fetching credentials from your vault (secret handles)

Instead of typing supported source credentials into Euno, the agent can fetch them from your secret store at connection time. Euno stores only a **handle** (an opaque name you define); the value is fetched through the agent when a connection is tested or a sync runs, used in memory, and never persisted in Euno.

{% hint style="info" %}
Secret handles require a recent agent release. Upgrade to `v1.0.0` or later and restart the container before following this section; agents on older releases keep tunneling normally but cannot serve handles.
{% endhint %}

Secret handles require agent release `v1.0.0` or later. The provider-specific troubleshooting codes below are returned only by those releases; earlier secret-handle images return the generic `cannot_fetch_dynamic_secret` code instead.

### 1. Give the agent host access to your vault

The agent authenticates to Azure Key Vault with the host's **managed identity** — no credential is ever written into Euno or the agent's configuration.

1. Enable a system-assigned managed identity on the machine running the agent (for a VM: `az vm identity assign -n <vm> -g <resource-group>`, or the Identity blade in the portal). Container Apps, AKS, and Arc-enabled servers work through their platform identity equivalents.
2. Grant that identity the **Key Vault Secrets User** role on the vault (or on the individual secrets):

```bash
az role assignment create \
  --assignee-object-id <vm-identity-principal-id> --assignee-principal-type ServicePrincipal \
  --role "Key Vault Secrets User" \
  --scope $(az keyvault show -n <vault-name> --query id -o tsv)
```

For vaults using legacy access policies instead of RBAC, an access policy with secret **Get** permission is the equivalent. The vault must be reachable from the agent host; a private endpoint is recommended.

### 2. Create `secrets.yaml` on the agent host

```yaml
version: 1
secrets:
  - handle: sql-prod-password
    type: azure_kv
    directions:
      vault_uri: https://<your-vault>.vault.azure.net/
      secret_name: <secret-name>
      # version: optional; omit to always use the latest (recommended for rotation)
```

* `handle` — the name shown in the Euno UI. It is the only thing Euno stores.
* `type` — use `azure_kv` (Azure Key Vault) in production. The `static` provider is available only for development and testing.
* `directions` — where the secret lives. No credentials go in this file: the agent authenticates to the vault with the host's **managed identity**, which needs the **Key Vault Secrets User** role on the vault.
* The file is an **allowlist**: Euno can only fetch handles listed here.

Keep the file owned by root with `chmod 600`, and mount it read-only into the container (add to the `docker-compose.yml` above):

```yaml
    volumes:
      - /etc/euno/secrets.yaml:/etc/euno/secrets.yaml:ro
```

The agent reads the file at startup — restart the container after changing it. If an explicitly configured file is missing, or a present file is invalid (for example, malformed YAML, missing or duplicate handles, or an unknown provider type), the agent logs the reason and keeps its tunnel connected. Secret-handle listing and resolution return `secrets_file_missing_or_invalid` until the file is fixed and the agent is restarted; integrations that use inline credentials are unaffected. If the default file is absent, the agent treats secret handles as unconfigured and returns an empty handle list.

### 3. Pick handles in the source form

In the source's **Advanced** section, once a local agent is selected, each credential field gains a **from agent** dropdown listing the agent's handles. Picking one disables the matching inline field — the value now comes from your vault. Choose **Enter value manually** to switch back.

The available handle-backed fields are:

| Source                 | Fields                                        |
| ---------------------- | --------------------------------------------- |
| **MySQL**              | Username and password                         |
| **SQL Server**         | Username and password                         |
| **Azure Data Factory** | Client secret                                 |
| **Power BI**           | Client secret                                 |
| **Snowflake**          | User, private key, and private-key passphrase |

### Security notes

* The value travels from the agent to Euno through the agent's outbound encrypted tunnel — it is never exposed to your network and never written to Euno storage, logs, or error reports.
* Every fetch is written to the agent's container logs as an audit line (handle and outcome only, never the value), so your team can export access records from your own log pipeline.
* The agent refuses to start if long-lived cloud credentials (for example `AZURE_CLIENT_SECRET`) are present in its environment — vault access is by machine identity only.

## Managing agents

| Action | How                                                                                                         |
| ------ | ----------------------------------------------------------------------------------------------------------- |
| Rename | Click **⋯** next to the agent → **Edit**. Change the name in the form. This does not affect the connection. |
| Stop   | Stop the agent container. The UI will show **Disconnected** after a refresh.                                |
| Delete | Click **⋯** next to the agent → **Delete**. Update any sources that used the agent before deleting.         |

{% hint style="warning" %}
Deleting an agent clears the local agent selection and any credential references effectively using the deleted agent from sources that used it. Those sources cannot connect until you open them, select a new agent or enter credentials inline, and save.
{% endhint %}

## Troubleshooting

| Symptom                                                                     | Fix                                                                                                                                                                                                                                  |
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Status stays **Disconnected** after starting the container                  | Check that `AGENT_ID` and `AGENT_SECRET` are correct. Inspect container logs for connection errors.                                                                                                                                  |
| Source run fails with "agent not connected"                                 | Ensure the agent container is running. Restart it if needed, then refresh the Local Agents page to confirm the status is **Connected** before re-running.                                                                            |
| Source run fails with "agent not found"                                     | The agent was deleted from Euno. Create a new agent and update the source's Advanced settings to select it.                                                                                                                          |
| Source run fails with `provider_auth_failed`                                | Confirm that the agent host has a managed identity and can obtain a token, then grant that identity the **Key Vault Secrets User** role on the configured vault. Also confirm that the vault belongs to the identity's Azure tenant. |
| Source run fails with `provider_denied`                                     | Confirm that the configured secret name and optional version exist in the vault and are available to read.                                                                                                                           |
| Source run fails with `fetch_timeout`                                       | Confirm that the vault URL names an existing vault and is reachable from the agent host, including DNS, firewall, and private-endpoint rules. A managed identity metadata timeout can also produce this code.                        |
| Source run fails with `cannot_fetch_dynamic_secret`                         | Upgrade to agent release `v1.0.0` or later and restart the container. If the failure continues, inspect the agent audit outcome and contact Euno support.                                                                            |
| Handle listing or a source run fails with `secrets_file_missing_or_invalid` | Fix `/etc/euno/secrets.yaml`, then restart the agent. The tunnel and integrations that use inline credentials remain available while the file is invalid.                                                                            |
| Source run fails with "Failed to connect to \[database]"                    | Verify that the database hostname is reachable from the machine running the agent container (not the Euno cloud). Check firewall rules and credentials.                                                                              |
| `no matching manifest for linux/arm64/v8`                                   | Add `platform: linux/amd64` to your `docker-compose.yml` under the `euno-local-agent` service. This applies when running on Apple Silicon Macs for local testing.                                                                    |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.euno.ai/setup-configuration/account-settings/local-agents.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
