Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/docs-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ jobs:
echo "::endgroup::"


- name: 🔒 Validate shared ACI docs and Private AI invariants
run: python3 .scripts/check_private_ai.py

- name: 🔗 Check internal links
run: |
echo "::group::🔗 Checking internal links"
Expand Down
75 changes: 75 additions & 0 deletions .scripts/check_private_ai.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env python3
"""Validate the canonical ACI mirror and Private AI documentation invariants."""

import hashlib
from pathlib import Path
import re
import subprocess
import sys
from urllib.parse import urlsplit

ROOT = Path(__file__).resolve().parents[1]
SHARED = ROOT / "snippets/aci"


def check_manifest():
errors = []
expected = {}
for line in (SHARED / "MANIFEST").read_text().splitlines():
match = re.fullmatch(r"([0-9a-f]{64}) ([A-Za-z0-9_-]+\.mdx)", line)
if not match:
errors.append(f"Invalid ACI manifest entry: {line!r}")
continue
digest, name = match.groups()
if name in expected:
errors.append(f"Duplicate ACI manifest entry: {name}")
expected[name] = digest
actual = {path.name for path in SHARED.iterdir() if path.name not in {"MANIFEST", "SOURCE"}}
if not expected or actual != set(expected):
errors.append(f"ACI manifest file set mismatch: missing={sorted(set(expected) - actual)}, extra={sorted(actual - set(expected))}")
for name, digest in expected.items():
path = SHARED / name
if path.is_file() and hashlib.sha256(path.read_bytes()).hexdigest() != digest:
errors.append(f"ACI snippet differs from MANIFEST: {name}; edit shared text in redpill-ai/redpill-docs and sync it here")
if not re.fullmatch(r"[0-9a-f]{40}\n", (SHARED / "SOURCE").read_text()):
errors.append("ACI SOURCE must contain the full canonical Git commit and a trailing newline")
return errors


def main():
try:
errors = check_manifest()
for path in (ROOT / "phala-cloud/confidential-ai").rglob("*.mdx"):
for number, line in enumerate(path.read_text().splitlines(), 1):
if re.match(r"^api\s*:", line):
value = line.split(":", 1)[1].strip().strip("\"'")
parts = value.split()
try:
url = urlsplit(parts[1]) if len(parts) == 2 else None
except ValueError:
url = None
if url is None or url.scheme not in {"http", "https"} or not url.netloc:
errors.append(f"{path.relative_to(ROOT)}:{number}: api metadata must use an absolute URL")
files = subprocess.run(
["git", "ls-files", "-z", "--cached", "--others", "--exclude-standard"],
cwd=ROOT, check=True, capture_output=True,
).stdout.split(b"\0")
prohibited = (b"mr" + b"-kms", b"mr" + b"_kms")
for name in files:
if not name:
continue
path = ROOT / name.decode("utf-8", errors="surrogateescape")
if path.is_file() and any(term in path.read_bytes().lower() for term in prohibited):
errors.append(f"{path.relative_to(ROOT)}: prohibited KMS measurement name")
except (OSError, UnicodeError, subprocess.CalledProcessError) as error:
print(f"Private AI validation could not complete: {error}", file=sys.stderr)
return 1
if errors:
print("\n".join(errors), file=sys.stderr)
return 1
print("Private AI checks passed: canonical ACI manifest, absolute API URLs, and measurement names")
return 0


if __name__ == "__main__":
sys.exit(main())
38 changes: 30 additions & 8 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@
"/phala-cloud/confidential-ai/gpu-tee-deployment-guide",
"/phala-cloud/confidential-ai/confidential-gpu/deploy-and-verify",
"/phala-cloud/confidential-ai/confidential-gpu/troubleshooting",
"/phala-cloud/confidential-ai/benchmark"
"/phala-cloud/confidential-ai/benchmark",
"/phala-cloud/confidential-ai/confidential-gpu/faqs"
]
},
{
Expand Down Expand Up @@ -745,13 +746,18 @@
"group": "Private AI",
"pages": [
"/phala-cloud/confidential-ai/overview",
"/phala-cloud/confidential-ai/confidential-model/how-it-works",
{
"group": "Getting Started",
"pages": [
"/phala-cloud/confidential-ai/confidential-model/confidential-ai-api",
"/phala-cloud/confidential-ai/confidential-model/playground",
"/phala-cloud/confidential-ai/confidential-model/migration-and-integrations",
"/phala-cloud/confidential-ai/confidential-model/anthropic-sdk"
"/phala-cloud/confidential-ai/confidential-model/anthropic-sdk",
"/phala-cloud/confidential-ai/confidential-model/integrations/openai-sdk",
"/phala-cloud/confidential-ai/confidential-model/integrations/agent-frameworks",
"/phala-cloud/confidential-ai/confidential-model/integrations/vercel-ai-sdk",
"/phala-cloud/confidential-ai/confidential-model/integrations/langfuse"
]
},
{
Expand All @@ -772,6 +778,7 @@
{
"group": "API Reference",
"pages": [
"/phala-cloud/confidential-ai/confidential-model/api-reference/overview",
"/phala-cloud/confidential-ai/confidential-model/api-reference/chat-completions",
"/phala-cloud/confidential-ai/confidential-model/api-reference/responses",
"/phala-cloud/confidential-ai/confidential-model/api-reference/messages",
Expand All @@ -783,9 +790,7 @@
"/phala-cloud/confidential-ai/confidential-model/api-reference/attestation",
"/phala-cloud/confidential-ai/confidential-model/api-reference/receipts",
"/phala-cloud/confidential-ai/confidential-model/api-reference/sessions",
"/phala-cloud/confidential-ai/confidential-model/api-reference/signature",
"/phala-cloud/confidential-ai/confidential-model/api-reference/embeddings",
"/phala-cloud/confidential-ai/confidential-model/api-reference/embedding-models"
"/phala-cloud/confidential-ai/confidential-model/api-reference/embeddings"
]
},
{
Expand All @@ -798,6 +803,7 @@
"/phala-cloud/confidential-ai/confidential-model/prompt-caching",
"/phala-cloud/confidential-ai/confidential-model/streaming",
"/phala-cloud/confidential-ai/confidential-model/attested-routing",
"/phala-cloud/confidential-ai/confidential-model/endpoint-policy",
"/phala-cloud/confidential-ai/confidential-model/zero-data-retention",
"/phala-cloud/confidential-ai/confidential-model/error-handling"
]
Expand All @@ -809,17 +815,17 @@
"/phala-cloud/confidential-ai/verify/typescript-sdk",
"/phala-cloud/confidential-ai/verify/verify-attestation",
"/phala-cloud/confidential-ai/verify/verify-signature",
"/phala-cloud/confidential-ai/confidential-model/receipts-and-sessions",
"/phala-cloud/confidential-ai/confidential-model/tcb-and-claims"
"/phala-cloud/confidential-ai/confidential-model/receipts-and-sessions"
]
},
{
"group": "Security Model",
"pages": [
"/phala-cloud/confidential-ai/confidential-model/trust-boundary",
"/phala-cloud/confidential-ai/confidential-model/channel-binding",
"/phala-cloud/confidential-ai/confidential-model/verified-upstreams",
"/phala-cloud/confidential-ai/confidential-model/providers",
"/phala-cloud/confidential-ai/confidential-model/e2ee-encryption",
"/phala-cloud/confidential-ai/confidential-model/e2ee-guide",
"/phala-cloud/confidential-ai/confidential-model/compliance-and-open-source"
]
},
Expand Down Expand Up @@ -940,6 +946,22 @@
]
},
"redirects": [
{
"source": "/phala-cloud/confidential-ai/confidential-model/channel-binding",
"destination": "/phala-cloud/confidential-ai/confidential-model/verified-upstreams"
},
{
"source": "/phala-cloud/confidential-ai/confidential-model/tcb-and-claims",
"destination": "/phala-cloud/confidential-ai/confidential-model/verified-upstreams"
},
{
"destination": "/phala-cloud/confidential-ai/confidential-model/api-reference/receipts",
"source": "/phala-cloud/confidential-ai/confidential-model/api-reference/signature"
},
{
"destination": "/phala-cloud/confidential-ai/confidential-model/api-reference/embeddings",
"source": "/phala-cloud/confidential-ai/confidential-model/api-reference/embedding-models"
},
{
"destination": "/phala-cloud/key-management/deploying-with-onchain-kms",
"source": "/phala-cloud/references/cloud-js-sdk/on-chain-kms-guide"
Expand Down
8 changes: 4 additions & 4 deletions phala-cloud/confidential-ai/agents/cline.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ This path does not verify attestation locally; use [Private AI Proxy](/phala-clo

## Check the Connection

Use Cline's **Verify** action, then run a read-only request in a disposable repository and confirm the selected provider and model.
Send a short read-only request in a disposable repository and confirm the selected provider and model.

## Troubleshooting

| Symptom | Check |
| --- | --- |
| Verify fails with the Proxy | Protected must be on; copy the client key again. |
| Verify fails without the Proxy | Keep `/v1` in the base URL and check the API key. |
| Tool calls fail | Choose a model that declares `tools` in the live catalog and repeat Verify. |
| Requests fail with the Proxy | Protected must be on; copy the client key again. |
| Requests fail without the Proxy | Keep `/v1` in the base URL and check the API key. |
| Tool calls fail | Choose a model that declares `tools` in the live catalog and send the request again. |

## Related

Expand Down
4 changes: 2 additions & 2 deletions phala-cloud/confidential-ai/agents/hermes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ Hermes speaks Chat Completions. Private AI Proxy configures it automatically.

1. Install [Private AI Proxy](/phala-cloud/confidential-ai/agents/private-ai-proxy), choose a **Phala** profile, sign in, and turn on **Protected**.
2. On the **Agents** screen, connect **Hermes**.
3. Start a new Hermes session; existing sessions stay on their original provider.
3. Start a new Hermes session to use the provider.

The app writes the provider into `~/.hermes/config.yaml` with an agent-scoped token for its local
The app writes the provider into `~/.hermes/config.yaml` (`%LOCALAPPDATA%\hermes\config.yaml` on Windows) with an agent-scoped token for its local
API, and restores the file when you disconnect or stop Protected.

From the CLI, the same connection is:
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 21 additions & 25 deletions phala-cloud/confidential-ai/agents/other-tools.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Every model on this endpoint runs in a TEE. These clients do not verify attestat

## Continue

Add a model to your local `~/.continue/config.yaml` using Continue's [OpenAI-compatible configuration](https://docs.continue.dev/customize/model-providers/top-level/openai). Keep any other models already in the file:
Add a model to your local `~/.continue/config.yaml` using Continue's [OpenAI-compatible configuration](https://docs.continue.dev/customize/model-providers/top-level/openai). Keep any other models already in the file. Set `PHALA_AI_API_KEY` in `~/.continue/.env` using Continue’s [local secrets](https://docs.continue.dev/faqs#managing-local-secrets-and-environment-variables) before using the reference below:

```yaml
name: Phala
Expand All @@ -29,7 +29,7 @@ models:
provider: openai
model: z-ai/glm-5.3
apiBase: https://inference.phala.com/v1
apiKey: YOUR_PHALA_API_KEY
apiKey: ${{ secrets.PHALA_AI_API_KEY }}
```

## Zed
Expand All @@ -56,7 +56,7 @@ Add this provider under `language_models` in your settings file using Zed's [Ope

## GitHub Copilot (VS Code BYOK)

Run **Chat: Manage Language Models**, choose **Add Models → Custom Endpoint**, name the group `Phala`, enter your Phala API key, and select **Chat Completions**. In the generated `chatLanguageModels.json`, keep the API-key input reference created by VS Code and configure the model as below. See the [Custom Endpoint documentation](https://code.visualstudio.com/docs/agent-customization/language-models#_add-a-custom-endpoint-model). This example uses the model's context window from the catalog and reserves 65,536 tokens for output, within the model's 1,048,576-token output maximum:
Run **Chat: Manage Language Models**, choose **Add Models → Custom Endpoint**, name the group `Phala`, enter your Phala API key, and select **Chat Completions**. In the generated `chatLanguageModels.json`, keep the API-key input reference created by VS Code and configure the model as below. See the [Custom Endpoint documentation](https://code.visualstudio.com/docs/agent-customization/language-models#_add-a-custom-endpoint-model). This example uses the model's context window from the catalog and reserves 65,536 tokens for output, so the configured input and output total the catalog’s 1,048,576-token context window:

```json
[
Expand All @@ -70,7 +70,7 @@ Run **Chat: Manage Language Models**, choose **Add Models → Custom Endpoint**,
"name": "Phala GLM 5.3",
"url": "https://inference.phala.com/v1/chat/completions",
"toolCalling": true,
"contextWindow": 1048576,
"maxInputTokens": 983040,
"maxOutputTokens": 65536
}
]
Expand All @@ -92,29 +92,25 @@ aider --model openai/z-ai/glm-5.3

## Goose

Save the following as `phala.json` in Goose's [`custom_providers` directory](https://goose-docs.ai/docs/getting-started/providers/#configure-custom-provider): `~/.config/goose/custom_providers/` on macOS/Linux, or `%APPDATA%\Block\goose\config\custom_providers\` on Windows. If you set `GOOSE_PATH_ROOT`, use `<GOOSE_PATH_ROOT>/config/custom_providers/` instead. Create the directory if needed:
Use Goose’s [custom-provider CLI setup](https://goose-docs.ai/docs/getting-started/providers/#configure-custom-provider):

```json
{
"name": "phala",
"engine": "openai",
"display_name": "Phala",
"description": "OpenAI-compatible confidential inference from Phala.",
"api_key_env": "PHALA_AI_API_KEY",
"base_url": "https://inference.phala.com/v1",
"dynamic_models": true,
"models": [],
"supports_streaming": true,
"model_doc_link": "https://docs.phala.com/phala-cloud/confidential-ai/confidential-model/confidential-ai-api",
"setup_steps": [
"Sign in to the Phala dashboard",
"Open Private AI, then API Keys, and create an API key",
"Copy the key and paste it above"
]
}
```bash
goose configure
```

With `PHALA_AI_API_KEY` set, run `goose configure`, choose **Configure Providers → Phala**, and select `z-ai/glm-5.3`. Dynamic discovery also lists the non-chat `jaredpalmer/kev-4b` decision model; choose a chat model.
Choose **Custom Providers → Add A Custom Provider**, select **OpenAI Compatible**, and enter:

| Prompt | Value |
| --- | --- |
| Name | Phala |
| API URL | `https://inference.phala.com/v1/chat/completions` |
| Authentication required | Yes |
| Credential | Static API key: paste your Phala API key |
| Available models | `z-ai/glm-5.3` |
| Streaming support | Yes |
| API base path | Leave empty |

Use the full Chat Completions endpoint. To set a model context limit, edit its `context_limit` in the provider JSON under `~/.config/goose/custom_providers/` (`%APPDATA%\Block\goose\config\custom_providers\` on Windows), using the model’s live `context_length`. Then choose **Configure Providers → Phala** and select the chat model. Decision models use a different API and cannot be used for this chat integration.

## AnythingLLM

Expand All @@ -129,7 +125,7 @@ Model context window: 1048576

## Cherry Studio

Open **Settings → Model Services → + Add Provider** and add a [custom provider](https://docs.cherryai.com.cn/docs/en-us/pre-basic/providers/zi-ding-yi-fu-wu-shang) with the values below. Enter the base URL in the OpenAI-compatible endpoint/API address row. Select **Add**, then **Get model list** and add `z-ai/glm-5.3`:
Open **Settings → Model Provider → + Add Provider** and add a [custom provider](https://cherryai.com/docs/en/) with the values below. Enter the base URL in **API Host**, select **Check** to test the connection, then **Sync models** and add `z-ai/glm-5.3`:

```text
Provider Name: Phala
Expand Down
2 changes: 1 addition & 1 deletion phala-cloud/confidential-ai/agents/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ description: Connect coding agents to Private AI through Private AI Proxy, or co
| DeepSeek Harness | `~/.dsh/cordis.patch.yml` and `.credentials.yaml` | |
| OpenCode | Provider in `~/.config/opencode/opencode.json` | [OpenCode](/phala-cloud/confidential-ai/agents/opencode) |
| Pi | Provider in `~/.pi/agent/models.json` | [Pi](/phala-cloud/confidential-ai/agents/pi) |
| Hermes | Provider in `~/.hermes/config.yaml` | [Hermes](/phala-cloud/confidential-ai/agents/hermes) |
| Hermes | Provider in `~/.hermes/config.yaml` (`%LOCALAPPDATA%\hermes\config.yaml` on Windows) | [Hermes](/phala-cloud/confidential-ai/agents/hermes) |
| OpenClaw | Native-host provider; restart required | [OpenClaw](/phala-cloud/confidential-ai/agents/openclaw) |
| Oh My Pi | Local token and models file; restart `omp` | |

Expand Down
Loading
Loading