docs: update serve api key requirement
maintainer edit: Align OpenAI-compatible API docs and examples with the new fail-closed api.api_key requirement while keeping /health documented as unauthenticated.
This commit is contained in:
+1
-1
@@ -107,7 +107,7 @@ File operations have path traversal protection, but:
|
|||||||
**API Calls:**
|
**API Calls:**
|
||||||
- All external API calls use HTTPS by default
|
- All external API calls use HTTPS by default
|
||||||
- Timeouts are configured to prevent hanging requests
|
- Timeouts are configured to prevent hanging requests
|
||||||
- The OpenAI-compatible API server must set `api.api_key` when binding to `0.0.0.0` or `::`; otherwise startup fails to prevent unauthenticated network access
|
- The OpenAI-compatible API server requires `api.api_key` for API routes; only `/health` remains unauthenticated for probes and load balancers
|
||||||
- Consider using a firewall to restrict outbound connections if needed
|
- Consider using a firewall to restrict outbound connections if needed
|
||||||
|
|
||||||
**WhatsApp:**
|
**WhatsApp:**
|
||||||
|
|||||||
@@ -204,6 +204,8 @@ Default API endpoint:
|
|||||||
http://127.0.0.1:8900
|
http://127.0.0.1:8900
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`nanobot serve` requires `api.apiKey`; send it as a Bearer token on API routes.
|
||||||
|
|
||||||
See [`openai-api.md`](./openai-api.md) for request examples.
|
See [`openai-api.md`](./openai-api.md) for request examples.
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|||||||
+18
-10
@@ -5,33 +5,32 @@ nanobot can expose a minimal OpenAI-compatible endpoint for local integrations:
|
|||||||
```bash
|
```bash
|
||||||
nanobot plugins enable api
|
nanobot plugins enable api
|
||||||
nanobot agent -m "Hello!"
|
nanobot agent -m "Hello!"
|
||||||
|
# Set api.apiKey first; see Authentication below.
|
||||||
nanobot serve
|
nanobot serve
|
||||||
```
|
```
|
||||||
|
|
||||||
Run the CLI check first. If `nanobot agent -m "Hello!"` fails, fix provider or config setup before debugging the API server. By default, the API binds to `127.0.0.1:8900`. You can change this in `config.json`.
|
Run the CLI check first. If `nanobot agent -m "Hello!"` fails, fix provider or config setup before debugging the API server. By default, the API binds to `127.0.0.1:8900`. You can change this in `config.json`. `nanobot serve` requires `api.apiKey`; set it before starting the server.
|
||||||
|
|
||||||
For setup help, see [`quick-start.md`](./quick-start.md), [`providers.md`](./providers.md), and [`troubleshooting.md`](./troubleshooting.md).
|
For setup help, see [`quick-start.md`](./quick-start.md), [`providers.md`](./providers.md), and [`troubleshooting.md`](./troubleshooting.md).
|
||||||
|
|
||||||
## Authentication
|
## Authentication
|
||||||
|
|
||||||
Local-only `127.0.0.1` usage does not require an API key. If you bind the API
|
`nanobot serve` requires `api.apiKey` for all API binds. Without it, startup
|
||||||
server to all interfaces with `api.host: "0.0.0.0"` or `"::"`, nanobot requires
|
fails before the agent is initialized. Keep the key secret and send it as a
|
||||||
`api.apiKey`; otherwise startup fails to avoid exposing an unauthenticated agent
|
Bearer token on API routes.
|
||||||
endpoint on the network.
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"api": {
|
"api": {
|
||||||
"host": "0.0.0.0",
|
"host": "127.0.0.1",
|
||||||
"port": 8900,
|
"port": 8900,
|
||||||
"apiKey": "${NANOBOT_API_KEY}"
|
"apiKey": "${NANOBOT_API_KEY}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
When `api.apiKey` is set, send it as a Bearer token on API routes. The health
|
The health endpoint remains unauthenticated so local probes and load balancers
|
||||||
endpoint remains unauthenticated so local probes and load balancers can still
|
can still check process health.
|
||||||
check process health.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl http://127.0.0.1:8900/v1/models \
|
curl http://127.0.0.1:8900/v1/models \
|
||||||
@@ -70,6 +69,7 @@ If `channel` points to a channel that is not enabled in your config, nanobot wil
|
|||||||
```bash
|
```bash
|
||||||
curl http://127.0.0.1:8900/v1/chat/completions \
|
curl http://127.0.0.1:8900/v1/chat/completions \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Authorization: Bearer $NANOBOT_API_KEY" \
|
||||||
-d '{
|
-d '{
|
||||||
"messages": [{"role": "user", "content": "hi"}],
|
"messages": [{"role": "user", "content": "hi"}],
|
||||||
"session_id": "my-session"
|
"session_id": "my-session"
|
||||||
@@ -83,6 +83,7 @@ Send images inline using the OpenAI multimodal content format:
|
|||||||
```bash
|
```bash
|
||||||
curl http://127.0.0.1:8900/v1/chat/completions \
|
curl http://127.0.0.1:8900/v1/chat/completions \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Authorization: Bearer $NANOBOT_API_KEY" \
|
||||||
-d '{
|
-d '{
|
||||||
"messages": [{"role": "user", "content": [
|
"messages": [{"role": "user", "content": [
|
||||||
{"type": "text", "text": "Describe this image"},
|
{"type": "text", "text": "Describe this image"},
|
||||||
@@ -98,11 +99,13 @@ Upload any supported file type (images, PDF, Word, Excel, PPT) via multipart:
|
|||||||
```bash
|
```bash
|
||||||
# Single file
|
# Single file
|
||||||
curl http://127.0.0.1:8900/v1/chat/completions \
|
curl http://127.0.0.1:8900/v1/chat/completions \
|
||||||
|
-H "Authorization: Bearer $NANOBOT_API_KEY" \
|
||||||
-F "message=Summarize this report" \
|
-F "message=Summarize this report" \
|
||||||
-F "files=@report.docx"
|
-F "files=@report.docx"
|
||||||
|
|
||||||
# Multiple files with session isolation
|
# Multiple files with session isolation
|
||||||
curl http://127.0.0.1:8900/v1/chat/completions \
|
curl http://127.0.0.1:8900/v1/chat/completions \
|
||||||
|
-H "Authorization: Bearer $NANOBOT_API_KEY" \
|
||||||
-F "message=Compare these files" \
|
-F "message=Compare these files" \
|
||||||
-F "files=@chart.png" \
|
-F "files=@chart.png" \
|
||||||
-F "files=@data.xlsx" \
|
-F "files=@data.xlsx" \
|
||||||
@@ -117,10 +120,13 @@ Supported file types:
|
|||||||
## Python (`requests`)
|
## Python (`requests`)
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
import os
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
resp = requests.post(
|
resp = requests.post(
|
||||||
"http://127.0.0.1:8900/v1/chat/completions",
|
"http://127.0.0.1:8900/v1/chat/completions",
|
||||||
|
headers={"Authorization": f"Bearer {os.environ['NANOBOT_API_KEY']}"},
|
||||||
json={
|
json={
|
||||||
"messages": [{"role": "user", "content": "hi"}],
|
"messages": [{"role": "user", "content": "hi"}],
|
||||||
"session_id": "my-session", # optional: isolate conversation
|
"session_id": "my-session", # optional: isolate conversation
|
||||||
@@ -134,11 +140,13 @@ print(resp.json()["choices"][0]["message"]["content"])
|
|||||||
## Python (`openai`)
|
## Python (`openai`)
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
import os
|
||||||
|
|
||||||
from openai import OpenAI
|
from openai import OpenAI
|
||||||
|
|
||||||
client = OpenAI(
|
client = OpenAI(
|
||||||
base_url="http://127.0.0.1:8900/v1",
|
base_url="http://127.0.0.1:8900/v1",
|
||||||
api_key="dummy",
|
api_key=os.environ["NANOBOT_API_KEY"],
|
||||||
)
|
)
|
||||||
|
|
||||||
resp = client.chat.completions.create(
|
resp = client.chat.completions.create(
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ def create_app(
|
|||||||
agent_loop: An initialized AgentLoop instance.
|
agent_loop: An initialized AgentLoop instance.
|
||||||
model_name: Model name reported in responses.
|
model_name: Model name reported in responses.
|
||||||
request_timeout: Per-request timeout in seconds.
|
request_timeout: Per-request timeout in seconds.
|
||||||
api_key: Optional API key for Bearer-token authentication.
|
api_key: API key for Bearer-token authentication on API routes.
|
||||||
"""
|
"""
|
||||||
app = web.Application(client_max_size=20 * 1024 * 1024) # 20MB for base64 images
|
app = web.Application(client_max_size=20 * 1024 * 1024) # 20MB for base64 images
|
||||||
app["agent_loop"] = agent_loop
|
app["agent_loop"] = agent_loop
|
||||||
|
|||||||
Reference in New Issue
Block a user