feat(docs): update Skill Proxy Migration Guide to clarify API key handling and usage markers
This commit is contained in:
parent
f584c3e53b
commit
7e2be324ff
|
|
@ -9,7 +9,7 @@ Applicable scenarios:
|
||||||
## 1. Migration Goals
|
## 1. Migration Goals
|
||||||
|
|
||||||
1. The skill no longer calls third-party domains directly.
|
1. The skill no longer calls third-party domains directly.
|
||||||
2. The skill no longer manages third-party API keys itself.
|
2. Real API keys are replaced by an API key marker in scripts being migrated.
|
||||||
3. All requests go through `/api/proxy/{provider}/...`.
|
3. All requests go through `/api/proxy/{provider}/...`.
|
||||||
4. Gateway handles:
|
4. Gateway handles:
|
||||||
- API key injection
|
- API key injection
|
||||||
|
|
@ -22,7 +22,11 @@ Applicable scenarios:
|
||||||
1. Keep provider names stable (for example, `runninghub`); do not encode model paths in provider names.
|
1. Keep provider names stable (for example, `runninghub`); do not encode model paths in provider names.
|
||||||
2. Only submit requests should carry `X-Idempotency-Key`; query requests should not.
|
2. Only submit requests should carry `X-Idempotency-Key`; query requests should not.
|
||||||
3. Use `X-Thread-Id` as a common context header whenever available.
|
3. Use `X-Thread-Id` as a common context header whenever available.
|
||||||
4. Use shorthand dot-paths in config extraction fields:
|
4. Replace API key usage in scripts with marker `API_KEY_MARKER = "__API_KEY_MARKER__"` at the actual usage location:
|
||||||
|
- If the script uses header auth, replace with `Authorization: Bearer __API_KEY_MARKER__`.
|
||||||
|
- If the script uses body auth, replace the body `apiKey` field value with `__API_KEY_MARKER__`.
|
||||||
|
- Choose header/body based on the script's real provider contract; do not force a single style.
|
||||||
|
5. Use shorthand dot-paths in config extraction fields:
|
||||||
- Correct: `taskId`, `status`, `usage.thirdPartyConsumeMoney`
|
- Correct: `taskId`, `status`, `usage.thirdPartyConsumeMoney`
|
||||||
- Incorrect: `$.taskId`, `'$'.taskId`
|
- Incorrect: `$.taskId`, `'$'.taskId`
|
||||||
|
|
||||||
|
|
@ -45,6 +49,7 @@ Implement:
|
||||||
- always sets `Content-Type: application/json`
|
- always sets `Content-Type: application/json`
|
||||||
- optionally sets `X-Thread-Id`
|
- optionally sets `X-Thread-Id`
|
||||||
- sets `X-Idempotency-Key` only when `include_idempotency=True`
|
- sets `X-Idempotency-Key` only when `include_idempotency=True`
|
||||||
|
- if this script authenticates via header, set `Authorization: Bearer __API_KEY_MARKER__`
|
||||||
|
|
||||||
### Step 3: Route submit calls through gateway
|
### Step 3: Route submit calls through gateway
|
||||||
|
|
||||||
|
|
@ -68,13 +73,15 @@ With:
|
||||||
And use:
|
And use:
|
||||||
- `headers=build_proxy_headers()`
|
- `headers=build_proxy_headers()`
|
||||||
|
|
||||||
### Step 5: Remove third-party API key logic from the skill
|
### Step 5: Replace third-party API key values with marker (do not keep real keys in scripts)
|
||||||
|
|
||||||
Remove:
|
Replace in the script being migrated:
|
||||||
- Loading `RUNNINGHUB_API_KEY` in the script
|
- Any real `Authorization: Bearer <real-key>` value -> `Authorization: Bearer __API_KEY_MARKER__`
|
||||||
- Building `Authorization: Bearer ...` in the script
|
- Any real body `apiKey` value -> `"apiKey": "__API_KEY_MARKER__"`
|
||||||
|
|
||||||
Reason: third-party credentials are injected by gateway.
|
Keep the original auth location (header vs body) unchanged unless provider API requirements changed.
|
||||||
|
|
||||||
|
Reason: gateway injects real credentials by replacing marker values at proxy forwarding time.
|
||||||
|
|
||||||
### Step 6: Keep essential error handling
|
### Step 6: Keep essential error handling
|
||||||
|
|
||||||
|
|
@ -150,10 +157,12 @@ from pathlib import Path
|
||||||
|
|
||||||
from dotenv import dotenv_values
|
from dotenv import dotenv_values
|
||||||
|
|
||||||
|
API_KEY_MARKER = "__API_KEY_MARKER__"
|
||||||
|
|
||||||
|
|
||||||
def load_skill_env() -> dict[str, str]:
|
def load_skill_env() -> dict[str, str]:
|
||||||
"""Load skill-local .env values."""
|
"""Load skill-local .env values."""
|
||||||
env_path = Path(__file__).parent.parent / ".env"
|
env_path = Path(__file__).parent / ".env"
|
||||||
return {
|
return {
|
||||||
key: value
|
key: value
|
||||||
for key, value in dotenv_values(env_path).items()
|
for key, value in dotenv_values(env_path).items()
|
||||||
|
|
@ -184,6 +193,13 @@ def build_proxy_headers(*, include_idempotency: bool = False) -> dict[str, str]:
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
headers["X-Idempotency-Key"] = str(uuid4())
|
headers["X-Idempotency-Key"] = str(uuid4())
|
||||||
return headers
|
return headers
|
||||||
|
|
||||||
|
|
||||||
|
# Optional helper when provider requires header auth in script contract:
|
||||||
|
def build_proxy_headers_with_auth(*, include_idempotency: bool = False) -> dict[str, str]:
|
||||||
|
headers = build_proxy_headers(include_idempotency=include_idempotency)
|
||||||
|
headers["Authorization"] = f"Bearer {API_KEY_MARKER}"
|
||||||
|
return headers
|
||||||
```
|
```
|
||||||
|
|
||||||
## 6. Common Pitfalls
|
## 6. Common Pitfalls
|
||||||
|
|
@ -206,7 +222,7 @@ For Docker-based sandbox execution, use:
|
||||||
## 7. Validation Checklist
|
## 7. Validation Checklist
|
||||||
|
|
||||||
1. No direct third-party domain calls remain in the skill script.
|
1. No direct third-party domain calls remain in the skill script.
|
||||||
2. The skill script no longer reads third-party API keys.
|
2. The skill script no longer contains real third-party API key values.
|
||||||
3. Submit uses proxy URL + `include_idempotency=True`.
|
3. Submit uses proxy URL + `include_idempotency=True`.
|
||||||
4. Query uses proxy URL + `include_idempotency=False`.
|
4. Query uses proxy URL + `include_idempotency=False`.
|
||||||
5. Config extraction fields use shorthand dot-paths only.
|
5. Config extraction fields use shorthand dot-paths only.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue