SimplaixSimplaix Gateway

Gateway Admin Guide

Deploy, configure, and manage a Simplaix Gateway instance.

This guide is for platform administrators who deploy and operate a Simplaix Gateway instance. You'll learn how to configure authentication, manage users and agents, define access policies, set up credential providers, and monitor the system.

Overview

As a Gateway Admin you are responsible for:

  1. Deploying the Gateway and configuring environment variables
  2. Managing users and assigning roles
  3. Registering agents and issuing runtime tokens
  4. Configuring tool providers (MCP servers) and access policies
  5. Setting up credential providers for the credential vault
  6. Monitoring via audit logs

Quick Start

Install the Gateway CLI globally and scaffold a config:

npm install -g @simplaix/simplaix-gateway
gateway init
gateway start
gateway admin create --email admin@example.com --password changeme

The Gateway starts on port 7521 by default. See Deployment for production deployment options.


Environment Variables

VariableRequiredDefaultDescription
JWT_SECRETYesSecret for signing/verifying JWTs (min 32 chars)
JWT_PUBLIC_KEYNoPEM public key for asymmetric JWT (RSA/EC)
JWT_ISSUERNosimplaix-gatewayJWT iss claim
JWT_AUDIENCENoJWT aud claim
JWT_EXPIRES_INNo24hToken expiration
JWT_EXTERNAL_ISSUERSNoJSON array of external IdP configs
ADMIN_EMAILNoAuto-created admin on first boot
ADMIN_PASSWORDNoPassword for auto-created admin
DATABASE_URLNoSQLite ~/.simplaix-gateway/data/gateway.dbSQLite file: path or postgres:// URL
CREDENTIAL_ENCRYPTION_KEYYes64-char hex key for AES-256-GCM
PORTNo7521HTTP port
GATEWAY_PUBLIC_URLNoPublic base URL for OAuth callbacks and pairing links
OAUTH_CALLBACK_BASE_URLNoOverride OAuth callback base separately
MCP_SERVER_URLNohttp://localhost:8080Default MCP server URL

External identity providers

To accept JWTs from Auth0, Azure AD, Okta, etc.:

# OIDC / JWKS
JWT_EXTERNAL_ISSUERS='[{
  "issuer": "https://your-tenant.auth0.com/",
  "jwksUri": "https://your-tenant.auth0.com/.well-known/jwks.json",
  "audience": "simplaix-gateway"
}]'

# Shared secret (HS256)
JWT_EXTERNAL_ISSUERS='[{
  "issuer": "https://auth.example.com",
  "secret": "shared-secret",
  "audience": "simplaix-gateway"
}]'

User Management

Roles

RolePermissions
adminFull access — manage all users, agents, providers, audit logs across all tenants
tenant_adminAdmin within own tenant — manage agents, providers, policies, view tenant audit logs
agent_creatorCreate and manage own agents, view own audit logs

Create a user

curl -X POST https://<your-gateway-url>/api/v1/admin/users \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "dev@example.com",
    "password": "securepass123",
    "name": "Alice",
    "tenantId": "tenant-acme",
    "roles": ["agent_creator"]
  }'

roles defaults to ["agent_creator"] if omitted.

Manage roles

# Assign a role
curl -X POST https://<your-gateway-url>/api/v1/admin/users/<user-id>/roles \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{"role": "tenant_admin"}'

# Remove a role
curl -X DELETE https://<your-gateway-url>/api/v1/admin/users/<user-id>/roles/tenant_admin \
  -H "Authorization: Bearer <admin-jwt>"

List and delete users

# List all users
curl https://<your-gateway-url>/api/v1/admin/users \
  -H "Authorization: Bearer <admin-jwt>"

# Delete a user
curl -X DELETE https://<your-gateway-url>/api/v1/admin/users/<user-id> \
  -H "Authorization: Bearer <admin-jwt>"

Agent Management

Register an agent

curl -X POST https://<your-gateway-url>/api/v1/admin/agents \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support Agent",
    "upstreamUrl": "http://support-agent:8000",
    "description": "Handles customer inquiries",
    "tenantId": "tenant-acme"
  }'

Request fields:

FieldRequiredDescription
nameYesDisplay name
upstreamUrlYesURL of the agent runtime
upstreamSecretNoBearer token sent to the upstream runtime
descriptionNoHuman-readable description
requireConfirmationNoRequire confirmation for all tool calls (default: false)
requiredCredentialsNoCredential requirements for the agent
tenantIdNoTenant scope

The response includes a runtime_token (art_...) — store it immediately, it is shown only once.

{
  "success": true,
  "agent": {
    "id": "abc123",
    "name": "Support Agent",
    "upstreamUrl": "http://support-agent:8000",
    "isActive": true,
    "requireConfirmation": false,
    "runtimeTokenPrefix": "art_xxxx",
    "createdAt": "2025-01-15T10:00:00Z"
  },
  "runtime_token": "art_xxxxxxxxxxxxxxxx..."
}

Kill switch

# Disable — all invocations immediately return 403
curl -X POST https://<your-gateway-url>/api/v1/admin/agents/<id>/disable \
  -H "Authorization: Bearer <admin-jwt>"

# Re-enable
curl -X POST https://<your-gateway-url>/api/v1/admin/agents/<id>/enable \
  -H "Authorization: Bearer <admin-jwt>"

Regenerate runtime token

curl -X POST https://<your-gateway-url>/api/v1/admin/agents/<id>/regenerate-token \
  -H "Authorization: Bearer <admin-jwt>"
# Returns a new runtime_token — the old one is immediately invalidated

API Key Management

API keys (gk_ prefix) provide server-to-server authentication for agent runtimes or external services calling the Gateway.

Create an API key

curl -X POST https://<your-gateway-url>/api/v1/admin/api-keys \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production Agent Server",
    "scopes": ["credentials:resolve"]
  }'

The full key is returned once in the response — store it securely.

Scopes

ScopeDescription
credentials:resolveResolve user credentials for injection (default)
credentials:readRead credential metadata
credentials:writeStore/update credentials on behalf of users

List and revoke

# List (shows keyPrefix, not the full key)
curl https://<your-gateway-url>/api/v1/admin/api-keys \
  -H "Authorization: Bearer <admin-jwt>"

# Revoke
curl -X DELETE https://<your-gateway-url>/api/v1/admin/api-keys/<key-id> \
  -H "Authorization: Bearer <admin-jwt>"

Tool Provider Management

Tool Providers map glob patterns to upstream MCP server endpoints — they define where tool calls are routed.

Create a tool provider

curl -X POST https://<your-gateway-url>/api/v1/admin/tool-providers \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Slack MCP",
    "pattern": "slack_*",
    "endpoint": "http://slack-mcp:3000",
    "authType": "bearer",
    "authSecret": "upstream-secret",
    "priority": 10
  }'
FieldRequiredDescription
nameYesDisplay name
patternYesGlob pattern matching tool names (e.g., slack_*, *)
endpointYesMCP server URL
authTypeNobearer, api_key, or none (default)
authSecretNoToken sent to upstream if authType is set
priorityNoHigher value = checked first when multiple patterns match
descriptionNoDescription

Fetch tools from a provider

curl https://<your-gateway-url>/api/v1/admin/tool-providers/<id>/tools \
  -H "Authorization: Bearer <admin-jwt>"

Provider Access Control

Access rules control which users and agents can invoke which tools on which providers.

Create an access rule

# Allow a specific user to access a provider
curl -X POST https://<your-gateway-url>/api/v1/admin/provider-access \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "subjectType": "user",
    "subjectId": "user-123",
    "providerId": "slack-provider-id",
    "action": "allow"
  }'

# Require confirmation for dangerous tools
curl -X POST https://<your-gateway-url>/api/v1/admin/provider-access \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "subjectType": "agent",
    "subjectId": "agent-abc",
    "providerId": "files-provider-id",
    "action": "require_confirmation",
    "toolPattern": "delete_*",
    "riskLevel": "critical"
  }'

# Deny a user from a sensitive provider
curl -X POST https://<your-gateway-url>/api/v1/admin/provider-access \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "subjectType": "user",
    "subjectId": "user-456",
    "providerId": "finance-provider-id",
    "action": "deny"
  }'

Rule fields:

FieldRequiredDescription
subjectTypeYesuser or agent
subjectIdYesUser ID or agent ID
providerIdYesTool provider ID, or * for all providers
actionYesallow, deny, or require_confirmation
toolPatternNoGlob pattern for tool names (default: *)
riskLevelNolow, medium, high, or critical

Set agent rules atomically

Replace all access rules for an agent in one request:

curl -X PUT https://<your-gateway-url>/api/v1/admin/provider-access/agent/<agent-id> \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "rules": [
      { "providerId": "slack-provider-id", "action": "allow" },
      { "providerId": "files-provider-id", "action": "require_confirmation", "toolPattern": "delete_*", "riskLevel": "critical" }
    ]
  }'

Policy evaluation

Test a policy before deploying:

curl -X POST https://<your-gateway-url>/api/v1/admin/provider-access/evaluate \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-123",
    "providerId": "slack-provider-id",
    "toolName": "slack_send_message",
    "agentId": "agent-abc"
  }'
# Returns: { "action": "allow|deny|require_confirmation", "risk": "low|...", "matchedRule": {...} }

Evaluation order

  1. User-level deny rules
  2. User-level allow rules
  3. Agent-level deny rules
  4. Agent-level allow rules
  5. Wildcard provider rules (deny, then allow)
  6. No match → denied by default

Credential Provider Setup

Credential Providers define how each service credential type works. Users store credentials against these providers; agents receive them as injected headers.

api_key provider

curl -X POST https://<your-gateway-url>/api/v1/credential-providers \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Stripe",
    "serviceType": "stripe",
    "authType": "api_key",
    "description": "Stripe payment API"
  }'

oauth2 provider

curl -X POST https://<your-gateway-url>/api/v1/credential-providers \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Google",
    "serviceType": "google",
    "authType": "oauth2",
    "config": {
      "clientId": "your-client-id",
      "clientSecret": "your-client-secret",
      "scopes": ["openid", "email", "https://www.googleapis.com/auth/calendar"]
    }
  }'

jwt provider

curl -X POST https://<your-gateway-url>/api/v1/credential-providers \
  -H "Authorization: Bearer <admin-jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Internal API",
    "serviceType": "internal_api",
    "authType": "jwt"
  }'

Supported auth types

TypeUse case
api_keyAPI keys (Stripe, OpenAI, etc.)
oauth2OAuth2 providers (Google, GitHub, Slack, etc.)
jwtService tokens and JWTs
basicUsername/password credentials

Multi-Tenancy

All resources can be scoped to a tenantId. Users and agents in different tenants are fully isolated — they cannot see or access each other's agents, credentials, or providers.

  • admin — can manage all tenants; pass tenantId in request body to scope operations
  • tenant_admin and agent_creator — automatically pinned to their own tenant

Resources with tenantId: null are global and visible to all tenants.


Audit Logs

Every tool call is recorded with full context.

# Recent logs
curl "https://<your-gateway-url>/api/v1/audit/logs?limit=50" \
  -H "Authorization: Bearer <admin-jwt>"

# Filter by agent, user, tool, or status
curl "https://<your-gateway-url>/api/v1/audit/logs?agent_id=abc&status=failed" \
  -H "Authorization: Bearer <admin-jwt>"

# Aggregate stats
curl https://<your-gateway-url>/api/v1/audit/stats \
  -H "Authorization: Bearer <admin-jwt>"

Query parameters: user_id, agent_id, tool_name, status, start_date, end_date, limit, offset

Log entry fields:

FieldDescription
userIdAuthenticated user
agentIdAgent that made the call
endUserIdEnd user the agent was acting on behalf of
providerIdTool provider that handled the call
toolNameTool invoked
argumentsTool call arguments (JSON)
resultTool response (JSON)
statuspending / confirmed / rejected / completed / failed
durationExecution time in ms
confirmedByUser who approved the confirmation (if applicable)

Production Checklist

  • Set a strong JWT_SECRET (openssl rand -hex 32)
  • Generate a CREDENTIAL_ENCRYPTION_KEY (openssl rand -hex 32)
  • Use PostgreSQL (DATABASE_URL=postgres://...)
  • Change the default admin password immediately after first login
  • Set GATEWAY_PUBLIC_URL for OAuth callbacks and pairing links
  • Configure JWT_EXTERNAL_ISSUERS if using an external IdP
  • Enable HTTPS via a reverse proxy (nginx, Caddy) or cloud platform
  • Set up monitoring for the /health endpoint

Admin API Reference

EndpointMethodDescription
Users
/api/v1/admin/usersGETList users
/api/v1/admin/usersPOSTCreate user
/api/v1/admin/users/:idGETGet user
/api/v1/admin/users/:idPUTUpdate user
/api/v1/admin/users/:idDELETEDelete user
/api/v1/admin/users/:id/rolesPOSTAssign role
/api/v1/admin/users/:id/roles/:roleDELETERemove role
Agents
/api/v1/admin/agentsGETList agents
/api/v1/admin/agentsPOSTRegister agent
/api/v1/admin/agents/:idGETGet agent
/api/v1/admin/agents/:idPUTUpdate agent
/api/v1/admin/agents/:idDELETEDelete agent
/api/v1/admin/agents/:id/disablePOSTKill switch — disable
/api/v1/admin/agents/:id/enablePOSTRe-enable
/api/v1/admin/agents/:id/regenerate-tokenPOSTNew runtime token
API Keys
/api/v1/admin/api-keysGETList keys
/api/v1/admin/api-keysPOSTCreate key
/api/v1/admin/api-keys/:idDELETERevoke key
Tool Providers
/api/v1/admin/tool-providersGETList providers
/api/v1/admin/tool-providersPOSTCreate provider
/api/v1/admin/tool-providers/:idGETGet provider
/api/v1/admin/tool-providers/:idPUTUpdate provider
/api/v1/admin/tool-providers/:idDELETEDelete provider
/api/v1/admin/tool-providers/:id/toolsGETFetch tools from MCP server
Provider Access
/api/v1/admin/provider-accessGETList rules
/api/v1/admin/provider-accessPOSTCreate rule
/api/v1/admin/provider-access/:idGETGet rule
/api/v1/admin/provider-access/:idPUTUpdate rule
/api/v1/admin/provider-access/:idDELETEDelete rule
/api/v1/admin/provider-access/agent/:idGETGet agent's rules
/api/v1/admin/provider-access/agent/:idPUTSet agent's rules (atomic)
/api/v1/admin/provider-access/evaluatePOSTEvaluate policy
Credential Providers
/api/v1/credential-providersGETList providers
/api/v1/credential-providersPOSTCreate provider
/api/v1/credential-providers/:idGETGet provider
/api/v1/credential-providers/:idPUTUpdate provider
/api/v1/credential-providers/:idDELETEDelete provider
/api/v1/credential-providers/by-service/:typeGETGet by service type
Audit
/api/v1/audit/logsGETQuery logs
/api/v1/audit/logs/:idGETGet log entry
/api/v1/audit/statsGETAggregate statistics
Health
/healthGETHealth check

On this page