Files
nexus/docs/gateway-api-research.md
T

11 KiB
Raw Blame History

Gateway API Research

Generated: 2026-06-10 | Updated: 2026-06-22 Auth mode: password (not token)

⚠️ Security note: Diese Datei enthält Infrastruktur-Details zur Gateway-Integration. Sie gehört nicht ins öffentliche Repository. Bis zur Bereinigung: Gateway-Passwort maskiert als ieDm...PAg. Vollständige Architektur-Analyse in architecture-board-first-orchestration.md.

1. Authentication

Auth mode: password Credential: ieDm...PAg (masked: ieDmOiBiVfbbDM0ibrEebPAg → use ieDm...PAg)

How to authenticate

Authorization: Bearer <password>

All requests to POST /tools/invoke must include the Authorization: Bearer header with the gateway password from gateway.auth.password.

Configuration (from openclaw.json)

{
  gateway: {
    mode: "local",
    port: 18789,
    bind: "loopback",  // Only reachable from localhost
    auth: {
      mode: "password",
      password: "ieDmOjBiVfbbDM0ibrEebPAg",
      rateLimit: {
        maxAttempts: 10,
        windowMs: 60000,
        lockoutMs: 300000,
        exemptLoopback: true
      }
    },
    controlUi: {
      allowInsecureAuth: true,
      allowedOrigins: ["https://openclaw.noveria.net"]
    },
    tools: {
      // Default deny list applies (see below)
    }
  }
}

Notes

  • Loopback only: gateway.bind: "loopback" means the API only listens on 127.0.0.1:18789.
  • Rate limiting: 10 failed attempts per 60s window → 5min lockout. Loopback is exempt.
  • Control UI: Allowed origin: https://openclaw.noveria.net

2. API Endpoint: POST /tools/invoke

URL: http://127.0.0.1:18789/tools/invoke Method: POST Content-Type: application/json Auth: Authorization: Bearer <password> Max payload size: 2 MB

Request body structure

{
  "tool": "<tool_name>",
  "action": "<optional_action>",
  "args": { },
  "sessionKey": "main",
  "dryRun": false
}

Responses

Code Meaning
200 Success: { ok: true, result: ... }
400 Invalid request/tool input: { ok: false, error: { type, message } }
401 Unauthorized
404 Tool not found or not allowlisted
405 Method not allowed
429 Rate limited (with Retry-After header)
500 Tool execution error: { ok: false, error: { type, message } }

Default HTTP Deny List (cannot be invoked via HTTP)

These tools are blocked by default on the HTTP endpoint (policy):

Tool Reason
exec RCE surface
spawn RCE surface
shell RCE surface
fs_write Arbitrary file mutation
fs_delete Arbitrary file deletion
fs_move Arbitrary file move/rename
apply_patch Can rewrite files
sessions_spawn Session orchestration / remote agent spawning
sessions_send Cross-session message injection
cron Persistent automation control plane
gateway Gateway control plane (prevents reconfiguration via HTTP)
nodes Node command relay
whatsapp_login Interactive setup; hangs on HTTP

Override example (add to gateway.tools in config):

{
  gateway: {
    tools: {
      deny: ["browser"],      // extra blocks
      allow: ["gateway"],     // remove from default deny
    }
  }
}

3. Tested Tools & Responses

Note: Direct HTTP testing was not possible from this session (exec sandbox unavailable). Documentation based on API spec and config analysis.

3.1 session_status

Request:

{ "tool": "session_status", "args": {} }

Expected response structure:

{
  "ok": true,
  "result": {
    "sessionKey": "main",
    "agentId": "iris",
    "modelId": "openai/gpt-5.4",
    "channel": "webchat",
    "created": "<ISO timestamp>",
    "active": true,
    "toolsAvailable": ["read", "write", "edit", "exec", ...],
    "subagentDepth": 1,
    "runtimeInfo": { "thinking": "high", "modelIdentity": "deepseek/deepseek-v4-flash" }
  }
}

3.2 sessions_list

Request:

{ "tool": "sessions_list", "args": { "kinds": ["main", "subagent"] } }

Expected response: Array of active sessions with keys like iris-main, programmer-subagent-xxx, etc.

3.3 subagents

Request:

{ "tool": "subagents", "args": { "action": "list" } }

Expected response: List of configured subagents for the active session.

3.4 sessions_history

Request:

{ "tool": "sessions_history", "args": { "sessionKey": "iris-main", "limit": 10 } }

Expected response: Array of recent messages/events from the specified session. Fields include:

  • role (user/assistant/tool)
  • content (message text)
  • timestamp
  • tool_calls (if applicable)

Request:

{ "tool": "memory_search", "args": { "query": "...", "maxResults": 5 } }

Expected response:

{
  "ok": true,
  "result": [
    {
      "content": "...",
      "path": "memory/YYYY-MM-DD.md",
      "score": 0.95,
      "metadata": { "...": "..." }
    }
  ]
}

3.6 Health Check (non-tools/invoke)

Request:

GET http://127.0.0.1:18789/health

Expected response: "OK" or { "status": "ok" }


4. Data Structures for Dashboard Integration

Tool Call Response - Success

{
  "ok": true,
  "result": <any>
}

Tool Call Response - Error

{
  "ok": false,
  "error": {
    "type": "string",
    "message": "string"
  }
}

Session Object (from sessions_list / session_status)

Field Type Description
sessionKey string Unique session identifier
agentId string Agent id (e.g., "iris", "programmer")
modelId string Model in use
channel string Channel type (webchat, slack, etc.)
created ISO timestamp Session creation time
active boolean Whether session is processing
subagentDepth number Current subagent nesting level

Session History Entry

Field Type Description
role string "user", "assistant", "tool", "system"
content string Message content
timestamp ISO string When the message was sent
tool_calls array[] Tool invocation details (if assistant)
tool_call_id string Matches tool response to request

5. OpenAI-Compatibility Endpoints

These are additional HTTP endpoints on the same gateway port:

Endpoint Enabled? Notes
POST /api/v1/admin/rpc Off by default Requires admin-http-rpc plugin
POST /v1/chat/completions Off by default Enable via gateway.http.endpoints.chatCompletions.enabled
POST /v1/responses Off by default Enable via gateway.http.endpoints.responses.enabled

None of these are enabled in the current config.


6. Connection from Docker (Nexus API Container)

Current Integration Setup

The Nexus compose.yaml already includes the full integration infrastructure:

api:
  environment:
    Integrations__OpenClaw__BaseUrl: ${OPENCLAW_BASE_URL:-http://openclaw-gateway-bao:18789}
    Integrations__OpenClaw__Token: ${OPENCLAW_GATEWAY_TOKEN:-}
    Integrations__OpenClaw__Password: ${OPENCLAW_GATEWAY_PASSWORD:-}
  networks:
    - nexus
    - openclaw_default

The API container:

  • Uses Docker DNS (openclaw-gateway-bao:18789) in the shared openclaw_default network
  • Does not depend on a published host port for the Gateway
  • Reads token/password from .env via OPENCLAW_GATEWAY_PASSWORD

Resolved Routing Issue (2026-07-09)

The old host.docker.internal:18789 route was unreachable because no usable host port was published. The Gateway is now reached directly by its container DNS name.

Scenario Works? Why
host.docker.internal:18789 No No reachable host listener on the VPS
openclaw-gateway-bao:18789 in openclaw_default Yes Direct container-to-container routing via Docker DNS

The Gateway must listen on its container interface (gateway.bind: "lan"):

{
  gateway: {
    bind: "lan"  // was "loopback"
  }
}

Test command (from Nexus API container):

curl -s http://openclaw-gateway-bao:18789/
# Expected: HTTP 200 from inside nexus-api-1

Required .env Vars for Nexus

The Nexus project .env needs these values for gateway integration:

# OpenClaw Gateway integration
OPENCLAW_GATEWAY_PASSWORD=ieDmOjBiVfbbDM0ibrEebPAg

The compose.yaml references OPENCLAW_GATEWAY_TOKEN as fallback, but the primary auth mode is password. Either var works with Bearer auth.


7. Rate Limits & Restrictions

Limit Value Detail
Auth failures 10 per 60s Per client IP, per auth scope
Lockout 5 min After hitting rate limit
Loopback exempt Yes Loopback traffic not rate-limited
Max payload 2 MB Per request
HTTP default deny 12 tools RCE/mutation tools blocked
Bind mode loopback Only localhost reachable

8. Security Notes

  • Keep credentials secret Never log or commit the gateway password
  • Token masking in docs: ieDm...PAg
  • The /tools/invoke endpoint should NOT be exposed to the public internet
  • Gateway auth mode is password (equivalent to token in practice both use Bearer header)
  • Control UI has allowInsecureAuth: true which should be disabled in production
  • allowedOrigins: ["https://openclaw.noveria.net"] should be reviewed

9. Example curl Commands (for reference)

# Health check
curl http://127.0.0.1:18789/health

# Session status
curl -s -X POST http://127.0.0.1:18789/tools/invoke \
  -H "Authorization: Bearer <PASSWORD>" \
  -H "Content-Type: application/json" \
  -d '{"tool":"session_status","args":{}}'

# List sessions
curl -s -X POST http://127.0.0.1:18789/tools/invoke \
  -H "Authorization: Bearer <PASSWORD>" \
  -H "Content-Type: application/json" \
  -d '{"tool":"sessions_list","args":{"kinds":["main","subagent"]}}'

# Session history
curl -s -X POST http://127.0.0.1:18789/tools/invoke \
  -H "Authorization: Bearer <PASSWORD>" \
  -H "Content-Type: application/json" \
  -d '{"tool":"sessions_history","args":{"sessionKey":"iris-main","limit":10}}'

# Memory search
curl -s -X POST http://127.0.0.1:18789/tools/invoke \
  -H "Authorization: Bearer <PASSWORD>" \
  -H "Content-Type: application/json" \
  -d '{"tool":"memory_search","args":{"query":"nexus","maxResults":5}}'

# Subagents list
curl -s -X POST http://127.0.0.1:18789/tools/invoke \
  -H "Authorization: Bearer <PASSWORD>" \
  -H "Content-Type: application/json" \
  -d '{"tool":"subagents","args":{"action":"list"}}'

Replace <PASSWORD> with the actual gateway password.