> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/agentgateway/agentgateway/llms.txt
> Use this file to discover all available pages before exploring further.

# Local configuration

> The runtime configuration structure — binds, listeners, routes, and backends — loaded from a YAML or JSON file with automatic hot reload.

Local configuration defines the full runtime behavior of the gateway: which ports to listen on, how to route traffic, which backends to proxy to, and what policies to apply. It lives in the same YAML or JSON file as [static configuration](/reference/static-config), alongside or below the `config` key.

The gateway watches the config file for changes. When you save an update, it reloads local configuration automatically — no restart required.

## File structure

A complete config file has two top-level sections:

* `config` — static global settings (optional; see [static config](/reference/static-config))
* `binds` — array of port bindings with listeners, routes, and backends

```yaml theme={null}
# Global static settings (optional)
config:
  logging:
    level: info
    format: json

# Runtime configuration
binds:
  - port: 3000
    listeners:
      - routes:
          - backends:
              - mcp:
                  targets:
                    - name: my-server
                      stdio:
                        cmd: npx
                        args: ["@modelcontextprotocol/server-everything"]
```

## YAML vs JSON

Both formats are supported. Use YAML for human-authored configs — it supports comments and is less verbose. Use JSON when generating configs programmatically.

<CodeGroup>
  ```yaml YAML theme={null}
  binds:
    - port: 3000
      listeners:
        - name: default
          protocol: HTTPS
          tls:
            cert: certs/cert.pem
            key: certs/key.pem
          routes:
            - backends:
                - host: localhost:8080
  ```

  ```json JSON theme={null}
  {
    "binds": [
      {
        "port": 3000,
        "listeners": [
          {
            "name": "default",
            "protocol": "HTTPS",
            "tls": {
              "cert": "certs/cert.pem",
              "key": "certs/key.pem"
            },
            "routes": [
              {
                "backends": [
                  { "host": "localhost:8080" }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
  ```
</CodeGroup>

## Top-level structure

<ParamField path="binds" type="object[]">
  Array of port bindings. Each bind defines a port and the listeners attached to it.

  <Expandable title="binds[] fields">
    <ParamField path="binds[].port" type="number" required>
      The TCP port to listen on.
    </ParamField>

    <ParamField path="binds[].listeners" type="object[]">
      Array of listeners attached to this port. Each listener can match a specific hostname and defines its own routes.

      See [Listeners reference →](/reference/listeners)
    </ParamField>
  </Expandable>
</ParamField>

## Binds and listeners

A **bind** opens a TCP port. Each bind can have one or more **listeners** that match traffic by hostname and protocol. Each listener defines a set of **routes** that map requests to **backends**.

```
binds
└── port: 3000
    └── listeners
        └── hostname: "*.example.com", protocol: HTTPS
            └── routes
                └── path: /api → backend: api-server
                └── path: /mcp → backend: mcp-server
```

### Listener fields

<ParamField path="binds[].listeners[].name" type="string">
  Optional name for the listener. Used for identification in logs and metrics.
</ParamField>

<ParamField path="binds[].listeners[].namespace" type="string">
  Namespace for the listener resource. Used in multi-tenant and Kubernetes deployments.
</ParamField>

<ParamField path="binds[].listeners[].hostname" type="string">
  Hostname this listener matches. Supports wildcards, for example `*.example.com`. When not set, the listener matches all hostnames on the port.
</ParamField>

<ParamField path="binds[].listeners[].protocol" type="string">
  Protocol for this listener. Accepted values: `HTTP`, `HTTPS`. When using `HTTPS`, provide a `tls` block.
</ParamField>

<ParamField path="binds[].listeners[].tls" type="object">
  TLS configuration. Required when `protocol` is `HTTPS`.

  <Expandable title="tls fields">
    <ParamField path="binds[].listeners[].tls.cert" type="string" required>
      Path to the PEM-encoded certificate file.
    </ParamField>

    <ParamField path="binds[].listeners[].tls.key" type="string" required>
      Path to the PEM-encoded private key file.
    </ParamField>

    <ParamField path="binds[].listeners[].tls.root" type="string">
      Path to the root CA certificate bundle for mTLS client verification.
    </ParamField>

    <ParamField path="binds[].listeners[].tls.cipherSuites" type="string[]">
      Optional allowlist of TLS cipher suites. Order is preserved.
    </ParamField>

    <ParamField path="binds[].listeners[].tls.minTLSVersion" type="string">
      Minimum TLS version to accept. Supported values: `TLS1_2`, `TLS1_3`.
    </ParamField>

    <ParamField path="binds[].listeners[].tls.maxTLSVersion" type="string">
      Maximum TLS version to accept. Supported values: `TLS1_2`, `TLS1_3`.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="binds[].listeners[].routes" type="object[]">
  Array of routes for this listener. Routes are evaluated in order; the first match wins.

  See [Routes reference →](/reference/routes)
</ParamField>

## Routes

A route matches incoming requests and forwards them to one or more backends. Routes support matching on path, headers, method, and query parameters.

```yaml theme={null}
routes:
  - name: mcp-route
    matches:
      - path:
          pathPrefix: /mcp
    policies:
      cors:
        allowOrigins:
          - "*"
        allowHeaders:
          - content-type
    backends:
      - mcp:
          targets:
            - name: my-server
              stdio:
                cmd: npx
                args: ["@modelcontextprotocol/server-everything"]
```

See the [Routes reference](/reference/routes) for full match and policy options.

## Backends

Backends define where traffic is sent. The local config supports several backend types:

<AccordionGroup>
  <Accordion title="MCP backend">
    Routes traffic to one or more MCP servers. Each server is defined as a target with a name and transport (stdio or SSE).

    ```yaml theme={null}
    backends:
      - mcp:
          targets:
            - name: filesystem
              stdio:
                cmd: npx
                args: ["@modelcontextprotocol/server-filesystem", "/data"]
            - name: github
              sse:
                host: https://mcp.github.com
    ```
  </Accordion>

  <Accordion title="HTTP / host backend">
    Route to a plain HTTP upstream using a `host` shorthand. The gateway resolves this into a full backend definition.

    ```yaml theme={null}
    backends:
      - host: localhost:9999
    ```
  </Accordion>

  <Accordion title="A2A backend">
    Route A2A agent traffic. Mark the route with `a2a: {}` to enable A2A processing and telemetry.

    ```yaml theme={null}
    routes:
      - policies:
          a2a: {}
        backends:
          - host: localhost:9999
    ```
  </Accordion>
</AccordionGroup>

See the [Backends reference](/reference/backends) for the full backend schema.

## Hot reload behavior

Agentgateway uses filesystem watching to detect config file changes. When the file is saved:

1. The new configuration is parsed and validated.
2. If validation passes, the runtime configuration is updated atomically.
3. Existing in-flight requests complete against the old configuration.
4. New requests use the updated configuration immediately.

If the updated file contains a syntax error or invalid field, the gateway logs an error and continues running with the previous configuration.

<Note>
  Static configuration fields (under `config`) are not reloaded on file change. Only `binds`, listeners, routes, backends, and policies are hot-reloaded.
</Note>

## Complete examples

<Tabs>
  <Tab title="MCP proxy">
    A minimal MCP proxy with CORS enabled for browser-based clients:

    ```yaml theme={null}
    # yaml-language-server: $schema=https://agentgateway.dev/schema/config
    binds:
      - port: 3000
        listeners:
          - routes:
              - policies:
                  cors:
                    allowOrigins:
                      - "*"
                    allowHeaders:
                      - mcp-protocol-version
                      - content-type
                      - cache-control
                    exposeHeaders:
                      - "Mcp-Session-Id"
                backends:
                  - mcp:
                      targets:
                        - name: everything
                          stdio:
                            cmd: npx
                            args: ["@modelcontextprotocol/server-everything"]
    ```
  </Tab>

  <Tab title="A2A proxy">
    An A2A proxy with JSON logging and access log annotations:

    ```yaml theme={null}
    config:
      logging:
        format: json
    frontendPolicies:
      accessLog:
        add:
          backend: backend
    binds:
      - port: 3000
        listeners:
          - routes:
              - policies:
                  cors:
                    allowOrigins:
                      - "*"
                    allowHeaders:
                      - content-type
                      - cache-control
                  a2a: {}
                backends:
                  - host: localhost:9999
    ```
  </Tab>

  <Tab title="TLS termination">
    HTTPS listener with TLS termination:

    ```yaml theme={null}
    # yaml-language-server: $schema=https://agentgateway.dev/schema/config
    binds:
      - port: 3000
        listeners:
          - name: default
            protocol: HTTPS
            tls:
              cert: certs/cert.pem
              key: certs/key.pem
            routes:
              - backends:
                  - mcp:
                      targets:
                        - name: everything
                          stdio:
                            cmd: npx
                            args: ["@modelcontextprotocol/server-everything"]
    ```
  </Tab>

  <Tab title="Multi-backend">
    Multiple MCP backends on a single port with per-path routing:

    ```yaml theme={null}
    config:
      logging:
        level: info
        format: json
      adminAddr: "0.0.0.0:15000"
      statsAddr: "0.0.0.0:15020"

    binds:
      - port: 3000
        listeners:
          - routes:
              - name: filesystem-route
                matches:
                  - path:
                      pathPrefix: /fs
                policies:
                  cors:
                    allowOrigins:
                      - "*"
                    allowHeaders:
                      - content-type
                      - mcp-protocol-version
                backends:
                  - mcp:
                      targets:
                        - name: filesystem
                          stdio:
                            cmd: npx
                            args:
                              - "@modelcontextprotocol/server-filesystem"
                              - "/data"

              - name: github-route
                matches:
                  - path:
                      pathPrefix: /github
                policies:
                  cors:
                    allowOrigins:
                      - "*"
                    allowHeaders:
                      - content-type
                      - mcp-protocol-version
                      - authorization
                backends:
                  - mcp:
                      targets:
                        - name: github
                          sse:
                            host: https://mcp.github.com
    ```
  </Tab>
</Tabs>

## Mapping to internal representation

Local configuration translates into an internal representation (IR) shared with XDS. Most fields map directly, but some are transformed for ergonomics:

| Local config field       | IR behavior                                                                           |
| ------------------------ | ------------------------------------------------------------------------------------- |
| `host: localhost:9999`   | Expanded into a full backend definition with hostname and port                        |
| `mcp.targets[].sse.host` | Resolved to a backend + TLS configuration based on the URL scheme                     |
| `tls.cert` / `tls.key`   | File paths are read at load time and stored as PEM bytes in the IR                    |
| Route `policies`         | Merged and applied at runtime; precedence handled by the proxy, not the control plane |

This translation layer means you can use convenient shorthands in local config that would not be valid in XDS, which expects fully resolved values.
