# Self-managed Context Gateway API examples

```json metadata
{
  "schema_version": 2,
  "title": "Self-managed Context Gateway API examples",
  "description": "Create the Gateways and the sample Upstream, mint an agent key, verify agent access, and rotate or revoke keys.",
  "categories": ["docs","operate","iris"],
  "tableOfContents": {"sections":[{"id":"set-connection-values","title":"Set connection values"},{"id":"create-the-gateways","title":"Create the Gateways"},{"id":"register-the-sample-upstream","title":"Register the sample Upstream"},{"id":"mint-an-agent-key","title":"Mint an agent key"},{"id":"verify-agent-access","title":"Verify agent access"},{"id":"rotate-or-revoke-agent-keys","title":"Rotate or revoke agent keys"},{"id":"hand-off-to-a-developer","title":"Hand off to a developer"},{"id":"use-the-cli-instead","title":"Use the CLI instead"}]}

,
  "codeExamples": []
}
```


Create sample Gateways for full and search mode, register the clinic directory on both, and issue an agent key. The [quickstart](https://redis.io/docs/latest/develop/ai/context-engine/context-gateway/quickstart) uses one of these Gateways. The [MCP walkthrough](https://redis.io/docs/latest/develop/ai/context-engine/context-gateway/mcp#stored-result-example) uses the search-mode Gateway with compression enabled.

Before you begin, [deploy the chart](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/deploy) and [load the admin token](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/authentication#control-plane-admin-token).

## Set connection values

Forward the Control Plane and the Identity Service in separate terminals, as in [Deploy](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/deploy#5-verify-pods-and-health), then export the connection values:

```bash
export IRIS_CONTEXT_GATEWAY_SERVICE_URL='http://localhost:9100'
export IRIS_IDENTITY_URL='http://localhost:9200'
export IRIS_IDENTITY_TOKEN='<identity-service-control-token>'
export IRIS_IDENTITY_TENANT='<tenant-id>'
umask 077
```

`IRIS_CONTEXT_GATEWAY_SERVICE_TOKEN` holds the admin token. For application deployment, use the Control Plane and Identity Service endpoints your platform exposes.

## Create the Gateways

These examples use Bash, cURL, jq, and `redis-cli`. Use a dedicated demo Surface database with JSON and Search support. Register it in both planes, separately from the Gateway database. Enable `compression.enabled` in the Data Plane and use a Gateway database with JSON and `maxmemory-policy noeviction`.

Choose the registry IDs:

```bash
export GATEWAY_DATABASE_ID='<gateway-database-id>'
export SURFACE_DATABASE_ID='<surface-database-id>'
```

Create a `FULL` mode Gateway with compression disabled, and a `SEARCH` mode Gateway with compression enabled:

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$IRIS_CONTEXT_GATEWAY_SERVICE_URL/iris/v1/context-gateway/gateways" \
  -H "Authorization: Bearer $IRIS_CONTEXT_GATEWAY_SERVICE_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name": "Front desk", "toolExposureMode": "FULL", "cache": "DISABLED", "compression": "DISABLED"}' > front-desk.json

jq -n --arg database "$GATEWAY_DATABASE_ID" '{
  name: "Operations", toolExposureMode: "SEARCH", databaseId: $database,
  cache: "DISABLED", compression: "ENABLED"
}' > operations-create.json
curl --fail-with-body --silent --show-error \
  -X POST "$IRIS_CONTEXT_GATEWAY_SERVICE_URL/iris/v1/context-gateway/gateways" \
  -H "Authorization: Bearer $IRIS_CONTEXT_GATEWAY_SERVICE_TOKEN" \
  -H 'Content-Type: application/json' \
  --data-binary @operations-create.json > operations.json

export FRONT_DESK_ID="$(jq -er '.gatewayId' front-desk.json)"
export OPERATIONS_ID="$(jq -er '.gatewayId' operations.json)"
jq '{gatewayId, mcpEndpoint, toolExposureMode, compression}' front-desk.json operations.json
```

The `SEARCH` mode Gateway explicitly enables compression. Creation fails if its database cannot support it. Cache remains disabled in this walkthrough. Compression also needs `compression.enabled` on the Data Plane. See [Cache and compression](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/configuration#cache-and-compression).

## Register the sample Upstream

Save the complete JSON model from [Write a data model](https://redis.io/docs/latest/develop/ai/context-engine/context-gateway/manage-context-surfaces#write-a-data-model) as `clinic-model.json`. It defines `Location` and `Provider`, including the `specialty` and `location_id` TAG fields. Load these synthetic records into the dedicated demo database. The commands replace only these five sample keys:

```bash
export SURFACE_REDIS_URL='<surface-redis-url>'
redis-cli -u "$SURFACE_REDIS_URL" JSON.SET location:clinic-a '$' \
  '{"id":"clinic-a","name":"Clinic A","city":"Boston"}'
redis-cli -u "$SURFACE_REDIS_URL" JSON.SET location:clinic-b '$' \
  '{"id":"clinic-b","name":"Clinic B","city":"Boston"}'
redis-cli -u "$SURFACE_REDIS_URL" JSON.SET provider:p1 '$' \
  '{"id":"p1","specialty":"cardiology","location_id":"clinic-a"}'
redis-cli -u "$SURFACE_REDIS_URL" JSON.SET provider:p2 '$' \
  '{"id":"p2","specialty":"cardiology","location_id":"clinic-a"}'
redis-cli -u "$SURFACE_REDIS_URL" JSON.SET provider:p3 '$' \
  '{"id":"p3","specialty":"cardiology","location_id":"clinic-b"}'
```

Use the TLS scheme `rediss://` when the database requires it. Keep the real connection URL out of source control. For a password, prefer `REDISCLI_AUTH` over placing the password in command arguments. Importers must normalize line breaks in TEXT fields to spaces before writing records.

Register this model on both Gateways. Sharing the Surface database is intentional here: both Gateways should expose the same demo records.

```bash
jq -n --arg database "$SURFACE_DATABASE_ID" --slurpfile model clinic-model.json '{
  name: "Scheduling", namespace: "scheduling", kind: "CONTEXT_SURFACE",
  contextSurface: {databaseId: $database, dataModel: $model[0]}
}' > surface-create.json

for gateway_id in "$FRONT_DESK_ID" "$OPERATIONS_ID"; do
  curl --fail-with-body --silent --show-error \
    -X POST "$IRIS_CONTEXT_GATEWAY_SERVICE_URL/iris/v1/context-gateway/gateways/$gateway_id/upstreams" \
    -H "Authorization: Bearer $IRIS_CONTEXT_GATEWAY_SERVICE_TOKEN" \
    -H 'Content-Type: application/json' \
    --data-binary @surface-create.json > "surface-$gateway_id.json"
  jq -e '(.initialCatalogFailure == null) and (.upstreamId != null)' "surface-$gateway_id.json"
done
```

If `initialCatalogFailure` is present, stop and fix the reported database or configuration error before continuing. Indexing happens in the background. Wait for indexing to finish before comparing result counts. The expected dataset has three cardiologists: two at Clinic A and one at Clinic B.

## Mint an agent key

Issue one key with a `use` grant on each Gateway:

```bash
jq -n --arg tenant "$IRIS_IDENTITY_TENANT" --arg a "$FRONT_DESK_ID" --arg b "$OPERATIONS_ID" '{
  name: "front-desk-agent",
  grants: [
    {tenant: $tenant, product: "context-gateway", resourceType: "gateway", resourceId: $a, actions: ["use"]},
    {tenant: $tenant, product: "context-gateway", resourceType: "gateway", resourceId: $b, actions: ["use"]}
  ]
}' > agent-grant.json

curl --fail-with-body --silent --show-error \
  -X POST "$IRIS_IDENTITY_URL/v1/api-keys" \
  -H "Authorization: Bearer $IRIS_IDENTITY_TOKEN" \
  -H 'Content-Type: application/json' \
  --data-binary @agent-grant.json > agent-key.json
export IRIS_CONTEXT_GATEWAY_API_KEY="$(jq -er '.token' agent-key.json)"
```

> [!WARNING]
> The response's `token` is the agent key, and it is returned only on creation or rotation. Save it in your secret manager and keep its `keyId`.

## Verify agent access

Use the returned endpoints rather than constructing MCP URLs. They must be reachable from the developer's machine:

```bash
export IRIS_CONTEXT_GATEWAY_URL="$(jq -er '.mcpEndpoint' front-desk.json)"
export SEARCH_GATEWAY_URL="$(jq -er '.mcpEndpoint' operations.json)"
python -m venv .venv
source .venv/bin/activate
pip install redis-iris
```

Use Python 3.11 or later. Run this program to authenticate and list both catalogs:

```python
import os

from redis_iris import ContextGateway

for setting in ("IRIS_CONTEXT_GATEWAY_URL", "SEARCH_GATEWAY_URL"):
    gateway = ContextGateway.from_env({
        "IRIS_CONTEXT_GATEWAY_URL": os.environ[setting],
        "IRIS_CONTEXT_GATEWAY_API_KEY": os.environ["IRIS_CONTEXT_GATEWAY_API_KEY"],
    })
    print(setting, [tool.name for tool in gateway.tools()])
```

The full-mode catalog includes `scheduling__filter_provider`. The search-mode catalog includes `search_tools`, `run_tool`, and the handle tools, including `run_tool_as_handle` and `count_results`. Continue with the [quickstart](https://redis.io/docs/latest/develop/ai/context-engine/context-gateway/quickstart) to call the sample tools.

## Rotate or revoke agent keys

Rotate a key to issue a new token for the same grants. The grace period keeps the old token valid while applications switch:

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$IRIS_IDENTITY_URL/v1/api-keys/<key-id>/rotate?graceSeconds=3600" \
  -H "Authorization: Bearer $IRIS_IDENTITY_TOKEN"
```

Revoke a key you no longer need:

```bash
curl --fail-with-body --silent --show-error \
  -X DELETE "$IRIS_IDENTITY_URL/v1/api-keys/<key-id>" \
  -H "Authorization: Bearer $IRIS_IDENTITY_TOKEN"
```

A revoked key stops working within the Identity Service cache lifetime, 300 seconds by default.

## Hand off to a developer

For the quickstart, give the developer the chosen Gateway’s `mcpEndpoint` as `IRIS_CONTEXT_GATEWAY_URL` and the agent key as `IRIS_CONTEXT_GATEWAY_API_KEY`. Use Operations for search mode or Front desk for full mode. For the MCP walkthrough, provide Operations as `IRIS_CONTEXT_GATEWAY_URL`. Give platform teams who register Upstreams the Control Plane URL and admin token for [Manage Gateways and Upstreams](https://redis.io/docs/latest/develop/ai/context-engine/context-gateway/manage-gateways). Remove the local key-response files after you save the token.

## Use the CLI instead

The `iris context-gateway` command-line interface (CLI) in the [redis-iris package](https://pypi.org/project/redis-iris/) also manages Gateways. Install the version pinned in the [quickstart](https://redis.io/docs/latest/develop/ai/context-engine/context-gateway/quickstart#install-the-client). With `IRIS_IDENTITY_URL` and `IRIS_IDENTITY_TOKEN` exported, create a Gateway, mint its agent key, and write the developer's environment file in one command:

```bash
iris context-gateway service create --name front-desk --write-env .env
```

`--write-env` writes `IRIS_CONTEXT_GATEWAY_URL`, `IRIS_CONTEXT_GATEWAY_ID`, and `IRIS_CONTEXT_GATEWAY_API_KEY` to the file with mode `0600`, and the key is never printed. Add `--tool-exposure-mode search` and `--database-id <gateway-database-id>` for the operations Gateway. `service key` mints an agent key. `iris identity keys list --product context-gateway` lists keys, and `iris identity keys revoke <key-id>` revokes one. See [Manage Gateways and Upstreams](https://redis.io/docs/latest/develop/ai/context-engine/context-gateway/manage-gateways) for every operation.

