From 34b073dbd2ba9e1806cd0e58d1f325d664e53000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Lange?= Date: Thu, 19 Mar 2026 00:13:44 +0100 Subject: [PATCH 1/2] docs: add deployment and opencode examples --- README.md | 3 + docs/INTEGRATIONS.md | 12 ++ docs/ONBOARDING.md | 6 + .../foundrygate-multi-provider-stack.yaml | 107 +++++++++++++++ docs/examples/openclaw-foundrygate-full.jsonc | 129 ++++++++++++++++++ docs/examples/opencode-foundrygate.json | 60 ++++++++ 6 files changed, 317 insertions(+) create mode 100644 docs/examples/foundrygate-multi-provider-stack.yaml create mode 100644 docs/examples/openclaw-foundrygate-full.jsonc create mode 100644 docs/examples/opencode-foundrygate.json diff --git a/README.md b/README.md index 5efaf9d..1d0f316 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,9 @@ Start here for the deeper deployment details: - [Integrations](./docs/INTEGRATIONS.md) - [Onboarding](./docs/ONBOARDING.md) - [Examples](./docs/examples) +- [OpenClaw integration starter](./openclaw-integration.jsonc) +- [Full OpenClaw example](./docs/examples/openclaw-foundrygate-full.jsonc) +- [Multi-provider stack example](./docs/examples/foundrygate-multi-provider-stack.yaml) - [First-wave AI-native starters](./docs/AI-NATIVE-MATRIX.md#first-wave-template-set-for-v110) - [Second-wave AI-native starters](./docs/AI-NATIVE-MATRIX.md#second-wave-template-set) - [Third-wave AI-native starters](./docs/AI-NATIVE-MATRIX.md#third-wave-template-set) diff --git a/docs/INTEGRATIONS.md b/docs/INTEGRATIONS.md index 481f545..6468461 100644 --- a/docs/INTEGRATIONS.md +++ b/docs/INTEGRATIONS.md @@ -21,6 +21,7 @@ Use: - [openclaw-integration.jsonc](../openclaw-integration.jsonc) - [examples/openclaw-foundrygate.jsonc](./examples/openclaw-foundrygate.jsonc) +- [examples/openclaw-foundrygate-full.jsonc](./examples/openclaw-foundrygate-full.jsonc) - `client_profiles.presets: ["openclaw"]` for a standard starting point Minimal direction: @@ -99,6 +100,16 @@ As with other clients, prefer token-like client tags over long free-form values If you want a small Node-facing helper instead of shell aliases, the separate npm package lives in [packages/foundrygate-cli](../packages/foundrygate-cli). +### opencode + +`opencode` can use FoundryGate as a custom OpenAI-compatible provider through its `provider` config. + +- starter: [examples/opencode-foundrygate.json](./examples/opencode-foundrygate.json) +- recommended header: `X-FoundryGate-Client: opencode` +- recommended model: pick one of the FoundryGate model ids exposed by `GET /v1/models`, usually `auto` + +The current opencode docs recommend `@ai-sdk/openai-compatible` for custom OpenAI-compatible providers and a custom `provider..options.baseURL` value for the gateway endpoint. This FoundryGate starter follows that pattern and keeps the provider-local model ids aligned with `GET /v1/models`. + ## AI-native app clients For future app-specific clients, keep the same OpenAI-compatible base URL and add one stable app header before creating multiple custom profiles. @@ -240,6 +251,7 @@ Starter snippets: - [examples/provider-local-worker.env.example](./examples/provider-local-worker.env.example) - [examples/provider-image-provider.yaml](./examples/provider-image-provider.yaml) - [examples/provider-image-provider.env.example](./examples/provider-image-provider.env.example) +- [examples/foundrygate-multi-provider-stack.yaml](./examples/foundrygate-multi-provider-stack.yaml) ## Client onboarding diff --git a/docs/ONBOARDING.md b/docs/ONBOARDING.md index 767f61c..865fd2d 100644 --- a/docs/ONBOARDING.md +++ b/docs/ONBOARDING.md @@ -51,6 +51,7 @@ Starter snippets: - [examples/provider-local-worker.env.example](./examples/provider-local-worker.env.example) - [examples/provider-image-provider.yaml](./examples/provider-image-provider.yaml) - [examples/provider-image-provider.env.example](./examples/provider-image-provider.env.example) +- [examples/foundrygate-multi-provider-stack.yaml](./examples/foundrygate-multi-provider-stack.yaml) ### 2. Verify provider health @@ -68,6 +69,8 @@ Starter snippets: Repeat the same path before introducing more routing complexity. +If you want a fuller multi-provider starting point instead of enabling one block at a time, use [examples/foundrygate-multi-provider-stack.yaml](./examples/foundrygate-multi-provider-stack.yaml) as a copy source and then trim it down to the providers that are actually available in your environment. + For many-provider rollouts, run the onboarding report after every provider change: ```bash @@ -126,6 +129,8 @@ OpenClaw: Starter file: [examples/openclaw-foundrygate.jsonc](./examples/openclaw-foundrygate.jsonc) +Fuller deployment example: [examples/openclaw-foundrygate-full.jsonc](./examples/openclaw-foundrygate-full.jsonc) + Delegated / many-agent example: - [examples/openclaw-delegated-request.json](./examples/openclaw-delegated-request.json) @@ -149,6 +154,7 @@ Starter files: - [examples/n8n-foundrygate-http-request.json](./examples/n8n-foundrygate-http-request.json) - [examples/cli-foundrygate-env.sh](./examples/cli-foundrygate-env.sh) +- [examples/opencode-foundrygate.json](./examples/opencode-foundrygate.json) - [examples/client-ai-native-app-profile.yaml](./examples/client-ai-native-app-profile.yaml) - [examples/swe-af-foundrygate.env.example](./examples/swe-af-foundrygate.env.example) - [examples/paperclip-foundrygate.env.example](./examples/paperclip-foundrygate.env.example) diff --git a/docs/examples/foundrygate-multi-provider-stack.yaml b/docs/examples/foundrygate-multi-provider-stack.yaml new file mode 100644 index 0000000..35a87ec --- /dev/null +++ b/docs/examples/foundrygate-multi-provider-stack.yaml @@ -0,0 +1,107 @@ +# Example FoundryGate stack for a local-first deployment with: +# - cloud chat providers +# - one local worker +# - one image-capable provider +# - OpenClaw, n8n, and CLI presets enabled +# +# Copy the relevant blocks into config.yaml rather than replacing the whole file. + +providers: + deepseek-chat: + backend: openai-compat + base_url: "${DEEPSEEK_BASE_URL:-https://api.deepseek.com/v1}" + api_key: "${DEEPSEEK_API_KEY}" + model: "deepseek-chat" + max_tokens: 8000 + tier: default + + deepseek-reasoner: + backend: openai-compat + base_url: "${DEEPSEEK_BASE_URL:-https://api.deepseek.com/v1}" + api_key: "${DEEPSEEK_API_KEY}" + model: "deepseek-reasoner" + max_tokens: 8000 + tier: reasoning + + gemini-flash-lite: + backend: google-genai + base_url: "${GEMINI_BASE_URL:-https://generativelanguage.googleapis.com/v1beta}" + api_key: "${GEMINI_API_KEY}" + model: "gemini-2.5-flash-lite" + max_tokens: 8000 + tier: cheap + + gemini-flash: + backend: google-genai + base_url: "${GEMINI_BASE_URL:-https://generativelanguage.googleapis.com/v1beta}" + api_key: "${GEMINI_API_KEY}" + model: "gemini-2.5-flash" + max_tokens: 8000 + tier: mid + + openrouter-fallback: + backend: openai-compat + base_url: "${OPENROUTER_BASE_URL:-https://openrouter.ai/api/v1}" + api_key: "${OPENROUTER_API_KEY}" + model: "deepseek/deepseek-chat" + max_tokens: 8000 + tier: fallback + + local-worker: + contract: local-worker + backend: openai-compat + base_url: "http://127.0.0.1:11434/v1" + api_key: "local" + model: "llama3" + tier: local + capabilities: + local: true + cloud: false + + image-provider: + contract: image-provider + backend: openai-compat + base_url: "http://127.0.0.1:9000/v1" + api_key: "${IMAGE_PROVIDER_API_KEY}" + model: "image-model" + tier: specialty + capabilities: + image_generation: true + image_editing: true + image: + policy_tags: ["editing", "balanced"] + max_outputs: 4 + supported_sizes: ["1024x1024", "1536x1024"] + +fallback_chain: + - deepseek-chat + - deepseek-reasoner + - gemini-flash + - openrouter-fallback + +client_profiles: + enabled: true + default: generic + presets: ["openclaw", "n8n", "cli"] + profiles: + generic: {} + openclaw: + prefer_tiers: ["default", "reasoning"] + n8n: + prefer_tiers: ["cheap", "default"] + local-only: + capability_values: + local: true + rules: [] + +routing_policies: + enabled: true + rules: + - name: n8n-cheap-default + match: + any: + - header_contains: + x-foundrygate-client: ["n8n"] + - client_profile: ["n8n"] + select: + prefer_tiers: ["cheap", "default"] diff --git a/docs/examples/openclaw-foundrygate-full.jsonc b/docs/examples/openclaw-foundrygate-full.jsonc new file mode 100644 index 0000000..a5ad6d3 --- /dev/null +++ b/docs/examples/openclaw-foundrygate-full.jsonc @@ -0,0 +1,129 @@ +// Full OpenClaw example for FoundryGate as the primary chat gateway. +// Merge the relevant blocks into ~/.openclaw/openclaw.json. +// +// Notes: +// - The ids under providers.foundrygate.models must match GET /v1/models +// from FoundryGate. +// - Keep direct providers only when you still want manual overrides outside +// the gateway. +// - If FoundryGate does not yet expose a real image-capable provider, keep +// imageModel on one direct provider until it does. +{ + "models": { + "mode": "merge", + "providers": { + "foundrygate": { + "baseUrl": "http://127.0.0.1:8090/v1", + "apiKey": "local", + "auth": "api-key", + "api": "openai-completions", + "models": [ + { + "id": "auto", + "name": "FoundryGate Auto-Router", + "contextWindow": 128000, + "maxTokens": 8000 + }, + { + "id": "deepseek-chat", + "name": "DeepSeek Chat (via FoundryGate)", + "contextWindow": 128000, + "maxTokens": 8000 + }, + { + "id": "deepseek-reasoner", + "name": "DeepSeek Reasoner (via FoundryGate)", + "contextWindow": 128000, + "maxTokens": 8000 + }, + { + "id": "gemini-flash-lite", + "name": "Gemini Flash-Lite (via FoundryGate)", + "contextWindow": 1000000, + "maxTokens": 8000 + }, + { + "id": "gemini-flash", + "name": "Gemini Flash (via FoundryGate)", + "contextWindow": 1000000, + "maxTokens": 8000 + }, + { + "id": "openrouter-fallback", + "name": "OpenRouter Fallback (via FoundryGate)", + "contextWindow": 128000, + "maxTokens": 8000 + } + ] + }, + "google": { + "baseUrl": "https://generativelanguage.googleapis.com/v1beta", + "apiKey": "${GEMINI_API_KEY}", + "auth": "api-key", + "api": "google-generative-ai", + "models": [ + { + "id": "gemini-2.5-flash", + "name": "Gemini 2.5 Flash", + "contextWindow": 1000000, + "maxTokens": 8000 + } + ] + } + } + }, + "agents": { + "defaults": { + "model": { + "primary": "foundrygate/auto", + "fallbacks": [] + }, + "imageModel": { + "primary": "google/gemini-2.5-flash", + "fallbacks": [] + }, + "models": { + "foundrygate/auto": { + "alias": "auto" + }, + "foundrygate/deepseek-chat": { + "alias": "ds" + }, + "foundrygate/deepseek-reasoner": { + "alias": "r1" + }, + "foundrygate/gemini-flash-lite": { + "alias": "lite" + }, + "foundrygate/gemini-flash": { + "alias": "flash" + }, + "foundrygate/openrouter-fallback": { + "alias": "or" + }, + "google/gemini-2.5-flash": { + "alias": "img" + } + }, + "contextTokens": 200000, + "heartbeat": { + "every": "12h", + "model": "foundrygate/gemini-flash-lite", + "suppressToolErrorWarnings": true + }, + "subagents": { + "maxConcurrent": 6, + "model": "foundrygate/auto" + } + } + }, + "commands": { + "native": "auto", + "nativeSkills": "auto", + "restart": true, + "ownerDisplay": "raw" + }, + "gateway": { + "mode": "local" + } +} diff --git a/docs/examples/opencode-foundrygate.json b/docs/examples/opencode-foundrygate.json new file mode 100644 index 0000000..1088a28 --- /dev/null +++ b/docs/examples/opencode-foundrygate.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "foundrygate": { + "npm": "@ai-sdk/openai-compatible", + "name": "FoundryGate (local gateway)", + "options": { + "baseURL": "http://127.0.0.1:8090/v1", + "apiKey": "local", + "headers": { + "X-FoundryGate-Client": "opencode" + } + }, + "models": { + "auto": { + "name": "FoundryGate Auto-Router", + "limit": { + "context": 128000, + "output": 8000 + } + }, + "deepseek-chat": { + "name": "DeepSeek Chat (via FoundryGate)", + "limit": { + "context": 128000, + "output": 8000 + } + }, + "deepseek-reasoner": { + "name": "DeepSeek Reasoner (via FoundryGate)", + "limit": { + "context": 128000, + "output": 8000 + } + }, + "gemini-flash-lite": { + "name": "Gemini Flash-Lite (via FoundryGate)", + "limit": { + "context": 1000000, + "output": 8000 + } + }, + "gemini-flash": { + "name": "Gemini Flash (via FoundryGate)", + "limit": { + "context": 1000000, + "output": 8000 + } + }, + "openrouter-fallback": { + "name": "OpenRouter Fallback (via FoundryGate)", + "limit": { + "context": 128000, + "output": 8000 + } + } + } + } + } +} From 32dcfbffbdf4cdd57c9d6fdffa58cbfc9617ce98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Lange?= Date: Thu, 19 Mar 2026 00:20:20 +0100 Subject: [PATCH 2/2] docs: add Kilo and BLACKBOX provider starters --- docs/CONFIGURATION.md | 9 ++++++++ docs/INTEGRATIONS.md | 4 ++++ docs/ONBOARDING.md | 4 ++++ .../foundrygate-multi-provider-stack.yaml | 21 +++++++++++++++++++ docs/examples/provider-blackbox.env.example | 4 ++++ docs/examples/provider-blackbox.yaml | 11 ++++++++++ docs/examples/provider-kilocode.env.example | 6 ++++++ docs/examples/provider-kilocode.yaml | 11 ++++++++++ 8 files changed, 70 insertions(+) create mode 100644 docs/examples/provider-blackbox.env.example create mode 100644 docs/examples/provider-blackbox.yaml create mode 100644 docs/examples/provider-kilocode.env.example create mode 100644 docs/examples/provider-kilocode.yaml diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 185ed3d..6de6e4b 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -42,6 +42,13 @@ Optional base URL overrides in `.env.example`: Additional optional provider entries in `config.yaml` reference further env vars when you uncomment them. +Examples in `docs/examples` also cover optional provider API keys such as: + +- `KILOCODE_API_KEY` +- `BLACKBOX_API_KEY` + +ClawRouter / BlockRun is different: its current public path is wallet-/x402-oriented rather than a normal API-key field, so it is better treated as a separate integration model instead of another `*_API_KEY` example. + ## Security Settings `config.yaml` exposes explicit security controls for the request surface: @@ -145,6 +152,8 @@ The repo ships ready-to-copy examples under [`docs/examples`](./examples): - cloud provider starter YAML - local-worker starter YAML - image-provider starter YAML +- Kilo Gateway starter YAML +- BLACKBOX AI starter YAML - matching provider `.env` examples ## Validation Helpers diff --git a/docs/INTEGRATIONS.md b/docs/INTEGRATIONS.md index 6468461..318f305 100644 --- a/docs/INTEGRATIONS.md +++ b/docs/INTEGRATIONS.md @@ -251,6 +251,10 @@ Starter snippets: - [examples/provider-local-worker.env.example](./examples/provider-local-worker.env.example) - [examples/provider-image-provider.yaml](./examples/provider-image-provider.yaml) - [examples/provider-image-provider.env.example](./examples/provider-image-provider.env.example) +- [examples/provider-kilocode.yaml](./examples/provider-kilocode.yaml) +- [examples/provider-kilocode.env.example](./examples/provider-kilocode.env.example) +- [examples/provider-blackbox.yaml](./examples/provider-blackbox.yaml) +- [examples/provider-blackbox.env.example](./examples/provider-blackbox.env.example) - [examples/foundrygate-multi-provider-stack.yaml](./examples/foundrygate-multi-provider-stack.yaml) ## Client onboarding diff --git a/docs/ONBOARDING.md b/docs/ONBOARDING.md index 865fd2d..4e641f1 100644 --- a/docs/ONBOARDING.md +++ b/docs/ONBOARDING.md @@ -51,6 +51,10 @@ Starter snippets: - [examples/provider-local-worker.env.example](./examples/provider-local-worker.env.example) - [examples/provider-image-provider.yaml](./examples/provider-image-provider.yaml) - [examples/provider-image-provider.env.example](./examples/provider-image-provider.env.example) +- [examples/provider-kilocode.yaml](./examples/provider-kilocode.yaml) +- [examples/provider-kilocode.env.example](./examples/provider-kilocode.env.example) +- [examples/provider-blackbox.yaml](./examples/provider-blackbox.yaml) +- [examples/provider-blackbox.env.example](./examples/provider-blackbox.env.example) - [examples/foundrygate-multi-provider-stack.yaml](./examples/foundrygate-multi-provider-stack.yaml) ### 2. Verify provider health diff --git a/docs/examples/foundrygate-multi-provider-stack.yaml b/docs/examples/foundrygate-multi-provider-stack.yaml index 35a87ec..18d9db8 100644 --- a/docs/examples/foundrygate-multi-provider-stack.yaml +++ b/docs/examples/foundrygate-multi-provider-stack.yaml @@ -78,6 +78,8 @@ fallback_chain: - deepseek-reasoner - gemini-flash - openrouter-fallback + # - kilocode + # - blackbox-free client_profiles: enabled: true @@ -105,3 +107,22 @@ routing_policies: - client_profile: ["n8n"] select: prefer_tiers: ["cheap", "default"] + +# Optional additional fallback providers with free-tier or free-model paths: +# +# providers: +# kilocode: +# backend: openai-compat +# base_url: "${KILOCODE_BASE_URL:-https://api.kilo.ai/api/gateway/v1}" +# api_key: "${KILOCODE_API_KEY}" +# model: "z-ai/glm-5:free" +# max_tokens: 8000 +# tier: fallback +# +# blackbox-free: +# backend: openai-compat +# base_url: "${BLACKBOX_BASE_URL:-https://api.blackbox.ai}" +# api_key: "${BLACKBOX_API_KEY}" +# model: "blackboxai/x-ai/grok-code-fast-1:free" +# max_tokens: 8000 +# tier: fallback diff --git a/docs/examples/provider-blackbox.env.example b/docs/examples/provider-blackbox.env.example new file mode 100644 index 0000000..b8a6337 --- /dev/null +++ b/docs/examples/provider-blackbox.env.example @@ -0,0 +1,4 @@ +# Example environment for BLACKBOX AI via FoundryGate. + +BLACKBOX_API_KEY=replace-me +BLACKBOX_BASE_URL=https://api.blackbox.ai diff --git a/docs/examples/provider-blackbox.yaml b/docs/examples/provider-blackbox.yaml new file mode 100644 index 0000000..3a7eae0 --- /dev/null +++ b/docs/examples/provider-blackbox.yaml @@ -0,0 +1,11 @@ +providers: + blackbox-free: + backend: openai-compat + base_url: "${BLACKBOX_BASE_URL:-https://api.blackbox.ai}" + api_key: "${BLACKBOX_API_KEY}" + model: "blackboxai/x-ai/grok-code-fast-1:free" + max_tokens: 8000 + tier: fallback + +fallback_chain: + - blackbox-free diff --git a/docs/examples/provider-kilocode.env.example b/docs/examples/provider-kilocode.env.example new file mode 100644 index 0000000..4ee7035 --- /dev/null +++ b/docs/examples/provider-kilocode.env.example @@ -0,0 +1,6 @@ +# Example environment for Kilo Gateway via FoundryGate. +# Kilo docs also describe anonymous access for some :free models, but using an +# explicit key is the more stable operator path. + +KILOCODE_API_KEY=replace-me +KILOCODE_BASE_URL=https://api.kilo.ai/api/gateway/v1 diff --git a/docs/examples/provider-kilocode.yaml b/docs/examples/provider-kilocode.yaml new file mode 100644 index 0000000..e8e9122 --- /dev/null +++ b/docs/examples/provider-kilocode.yaml @@ -0,0 +1,11 @@ +providers: + kilocode: + backend: openai-compat + base_url: "${KILOCODE_BASE_URL:-https://api.kilo.ai/api/gateway/v1}" + api_key: "${KILOCODE_API_KEY}" + model: "z-ai/glm-5:free" + max_tokens: 8000 + tier: fallback + +fallback_chain: + - kilocode