Skip to content

Commit 0b3973a

Browse files
fix(oracle): clarify model discovery setup
1 parent dffd8b6 commit 0b3973a

5 files changed

Lines changed: 185 additions & 1 deletion

File tree

docs/advanced/configuration.mdx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,17 @@ providers:
270270
- gemini-1.5-pro
271271
```
272272

273+
<Note>
274+
For Oracle, prefer YAML configuration over env-only auto-discovery. Oracle
275+
inference can work even when the upstream `/models` endpoint is unavailable,
276+
so setting `models:` gives GoModel a reliable fallback inventory. See the
277+
[Oracle guide](/guides/oracle) for the required OCI policy and a tested
278+
configuration. Automatic model discovery is not yet a reliable, validated
279+
path for this provider: GoModel can try Oracle's OpenAI-compatible `/models`
280+
endpoint, but Oracle may not return a usable inventory there. OCI-native
281+
Oracle model discovery is not integrated yet.
282+
</Note>
283+
273284
### Ollama (Local Models)
274285

275286
Ollama does not require an API key. Set the base URL to enable it:

docs/docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"group": "Guides",
2020
"pages": [
2121
"guides/openclaw",
22+
"guides/oracle",
2223
"guides/claude-code",
2324
"guides/codex",
2425
"guides/opencode-and-other-agents"

docs/guides/oracle.mdx

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
---
2+
title: "Using GoModel with Oracle Generative AI"
3+
description: "Configure Oracle's OpenAI-compatible Generative AI endpoint in GoModel, including the required OCI policy and model fallback."
4+
---
5+
6+
GoModel works with Oracle Generative AI through Oracle's OpenAI-compatible
7+
endpoint.
8+
9+
Flow:
10+
11+
`Client -> GoModel -> Oracle Generative AI`
12+
13+
## Before you start
14+
15+
- Create an Oracle Generative AI API key.
16+
- Add an OCI IAM policy for `generativeaiapikey`.
17+
- Choose a supported Oracle region and model.
18+
- Prefer YAML configuration for Oracle so you can set `models:`.
19+
20+
## 1. Add the OCI policy
21+
22+
For a simple test setup, this tenancy-level policy is enough:
23+
24+
```text
25+
Allow any-user to use generative-ai-family in tenancy where ALL {request.principal.type='generativeaiapikey'}
26+
```
27+
28+
This allows Oracle Generative AI bearer API keys to call the inference APIs.
29+
30+
For production, narrow this policy to a specific compartment, API key, or model
31+
instead of leaving it tenancy-wide.
32+
33+
## 2. Set the Oracle endpoint and API key
34+
35+
Use Oracle's OpenAI-compatible inference base URL for your region. For Chicago:
36+
37+
```bash
38+
export ORACLE_BASE_URL="https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/v1"
39+
export ORACLE_API_KEY="..."
40+
```
41+
42+
## 3. Configure Oracle in GoModel
43+
44+
Use a YAML provider block and set `models:` explicitly:
45+
46+
```yaml
47+
providers:
48+
oracle:
49+
type: oracle
50+
base_url: "${ORACLE_BASE_URL}"
51+
api_key: "${ORACLE_API_KEY}"
52+
models:
53+
- openai.gpt-oss-120b
54+
```
55+
56+
Why `models:` matters:
57+
58+
- Oracle inference works through `chat/completions` and `responses`
59+
- Oracle's `/models` endpoint may not be available for this API-key flow
60+
- GoModel can fall back to the configured model list when `/models` is
61+
unavailable
62+
63+
For Oracle, YAML is the recommended path. Environment-only auto-discovery is
64+
not enough if you need the configured-model fallback.
65+
66+
## Current status
67+
68+
What is integrated today:
69+
70+
- Oracle's OpenAI-compatible inference endpoints
71+
- manual model configuration through `models:`
72+
- GoModel `/v1/models` from the configured-model fallback
73+
74+
What is not yet validated as reliable:
75+
76+
- Oracle's OpenAI-compatible `/models` endpoint for automatic model discovery
77+
78+
What is not integrated yet:
79+
80+
- native Oracle model auto-discovery through OCI APIs
81+
- automatic population of the Oracle model inventory without `models:`
82+
83+
If Oracle later exposes a reliable `/models` endpoint for this API-key flow, or
84+
GoModel adds a separate OCI-native discovery path, this manual `models:`
85+
requirement can be relaxed.
86+
87+
## 4. Start GoModel
88+
89+
```bash
90+
go run ./cmd/gomodel
91+
```
92+
93+
## 5. Verify the model registry
94+
95+
```bash
96+
curl -s http://localhost:8080/v1/models
97+
```
98+
99+
Expected result:
100+
101+
- a `200 OK`
102+
- an Oracle-owned model such as `oracle/openai.gpt-oss-120b`
103+
104+
## 6. Verify Responses
105+
106+
```bash
107+
curl -s http://localhost:8080/v1/responses \
108+
-H "Content-Type: application/json" \
109+
-d '{
110+
"model": "openai.gpt-oss-120b",
111+
"input": "Reply with the single word ok."
112+
}'
113+
```
114+
115+
Expected result:
116+
117+
- a `200 OK`
118+
- final output text containing `ok`
119+
120+
## 7. Verify Chat Completions
121+
122+
```bash
123+
curl -s http://localhost:8080/v1/chat/completions \
124+
-H "Content-Type: application/json" \
125+
-d '{
126+
"model": "openai.gpt-oss-120b",
127+
"messages": [{"role": "user", "content": "Reply with the single word ok."}],
128+
"max_tokens": 80
129+
}'
130+
```
131+
132+
Use a high enough `max_tokens` budget. Some Oracle-backed reasoning models can
133+
spend short completions on reasoning content before emitting final assistant
134+
text.
135+
136+
## Troubleshooting
137+
138+
- `404 Authorization failed or requested resource not found`
139+
Usually means the Generative AI API key policy is missing, the region is
140+
wrong, or the model is not available to the account.
141+
- `model registry has no models`
142+
Add `models:` to the Oracle provider config so GoModel can use the fallback.
143+
- OCI CLI works but Oracle bearer requests fail
144+
These are different auth flows. OCI CLI uses API signing keys; Oracle
145+
Generative AI inference uses the Generative AI bearer API key.
146+
147+
## References
148+
149+
- Oracle API keys overview: https://docs.oracle.com/en-us/iaas/Content/generative-ai/api-keys.htm
150+
- Oracle API key permissions: https://docs.oracle.com/en-us/iaas/Content/generative-ai/add-api-permission.htm
151+
- Oracle OpenAI-compatible endpoint: https://docs.oracle.com/en-us/iaas/Content/generative-ai/oci-openai.htm

internal/providers/oracle/oracle.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package oracle
22

33
import (
44
"context"
5+
"fmt"
56
"io"
67
"log/slog"
78
"net/http"
@@ -63,7 +64,10 @@ func (p *Provider) ListModels(ctx context.Context) (*core.ModelsResponse, error)
6364
resp, err := p.compat.ListModels(ctx)
6465
if len(p.configuredModels) == 0 {
6566
if err != nil {
66-
return nil, err
67+
return nil, fmt.Errorf(
68+
"oracle ListModels failed: %w; configure providers.<name>.models to use Oracle when upstream /models is unavailable",
69+
err,
70+
)
6771
}
6872
return resp, nil
6973
}

internal/providers/oracle/oracle_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"net/http"
77
"net/http/httptest"
8+
"strings"
89
"testing"
910

1011
"gomodel/internal/core"
@@ -111,6 +112,22 @@ func TestListModels_ReturnsUpstreamInventoryWhenNoConfiguredModels(t *testing.T)
111112
}
112113
}
113114

115+
func TestListModels_ReturnsActionableErrorWhenUpstreamFailsWithoutConfiguredModels(t *testing.T) {
116+
server := httptest.NewServer(http.NotFoundHandler())
117+
defer server.Close()
118+
119+
provider := NewWithHTTPClient("oracle-key", server.Client(), llmclient.Hooks{}, nil)
120+
provider.SetBaseURL(server.URL)
121+
122+
_, err := provider.ListModels(context.Background())
123+
if err == nil {
124+
t.Fatal("expected error, got nil")
125+
}
126+
if !strings.Contains(err.Error(), "configure providers.<name>.models") {
127+
t.Fatalf("err = %q, want mention of providers.<name>.models", err)
128+
}
129+
}
130+
114131
func TestEmbeddings_ReturnsUnsupportedError(t *testing.T) {
115132
provider := NewWithHTTPClient("oracle-key", nil, llmclient.Hooks{}, nil)
116133

0 commit comments

Comments
 (0)