Portal
In plain words: Cloud Models (remote APIs)
Describes a Cloud Model (Portal): a remote API provider declared in a config file, with no container or local GPU use. Declaring one names a possible data path but does not yet allow sending data.
- 1The Traffic Controller currently refuses every Cloud Model grant until the Privacy Filter exists.
- 2No automatic fallback from a failed local call to the cloud.
- 3Probing is off by default; LychD never starts, stops or repairs the provider.
Partial Declarations and probes exist; actual cloud calls are blocked.
Words on this page, decoded click one for its card
Cloud Model Portal
An AI model hosted somewhere else, reached over the internet.
It's like: Buying power from the grid: convenient, but someone else controls it.
Click a dot to open that part's card.
Beyond the rift, another sky keeps its own thunder.
A PortalCloud Model is a remote, API-backed Animator declared by a provider-specific RuneService Config File. It has no container and consumes no local VRAM. Its connector runs inside the trusted VesselEngine Room, where it may read the one Podman secret explicitly mounted for it.
The credential shares that trust boundary: file permissions do not hide it from code already executing inside the VesselEngine Room.
LychD does not own the remote service's lifecycle. PortalCloud Model capabilities are
dedicated=False and is_dynamic=False: the OrchestratorStage Manager cannot start, stop, load, or repair the
provider.
Portal Roads owns the choice between direct server APIs, BYOK gateways, aggregators, human coding subscriptions, subscription bridges, and local inference. A provider or dashboard appearing there is a candidate classification, not a delivered connector or endorsement.
Egress Is a Deliberate Boundary
Declaring a PortalCloud Model names a possible egress path; it does not authorize one
A matching PortalCloud Model may enter the registry, but DispatcherTraffic Controller currently refuses every PortalCloud Model grant because the typed egress-admission path is absent. Payload privatization, secure-mode, local-before-paid, and x402 gates are not current enforcement. Declare only a credential, data boundary, and spend profile that could become eligible after those gates are delivered.
Three limits matter:
- No automatic cloud replay. A failed local call is not replayed through a PortalCloud Model; no current
FallbackModelpath exists. - No probe egress by default.
probe = falseprevents the registry's optional/modelsrequest. The resulting route remains unverifiedUNKNOWNand cannot receive a grant; the separate PortalCloud Model quarantine also refuses it before transmission. - No hidden remote lifecycle. Binding writes no PortalCloud Model Quadlet and contacts no provider. It validates intent, proves named-secret presence, and mounts the reference into the VesselEngine Room.
With probing off, the registry reports the route as UNKNOWN; a declaration alone cannot
establish WARM. Enabling it permits the current
two-second unauthenticated GET <base_url>/models probe and validation of the returned
data[*].id inventory. Malformed inventory or the absence of the declared model id produces
ERROR. A credentialed provider can reject this probe even if its ordinary authenticated model
call would work.
Read the result as a readiness observation only. It cannot bypass the current all-Portal dispatch quarantine.
State of Work owns the absent egress gate. The documented anonymization PatternWorkflow does not authorize transmission.
Qualify disclosure accounting locally
The opt-in closed-diagnostic-recording@1 profile exercises durable decisions and consumed
capacity using only the existing closed diagnostic fixture and a concrete local recorder.
Its host pins a synthetic export consumer and expected binding independently of the Cut.
The acceptance witness must retain consumed host/purpose/Cut limits across new identifiers and
service reconstruction, refuse old seals and copied claims, and record exactly the verified bytes.
The database retains restricted custody rather than source or candidate bodies.
Run its disposable-PostgreSQL receipts with:
make test-containers CONTAINER_TEST_TARGETS="tests/integration/test_privacy_disclosure_pg.py tests/integration/test_privacy_disclosure_migrations_pg.py"
The command requires the container-test environment described in
Contributing. An explicit
LYCHD_PRIVACY_TEST_DATABASE_URL selects a disposable database supplied by the operator instead;
the profile never selects an application database automatically.
This profile opens no network road and changes no PortalCloud Model grant. Actual peer enrollment, full envelope verification, transport and native wait/adoption remain separate work. Its law is in Security and Persistence; State of Work owns delivery.
Declare and inspect one Portal
This rite assumes a summoned host. Run its commands from the stable Summoning checkout, under the same operator user and XDG environment. For a first installation, begin with Summoning.
1. Admit the provider schema
Resolve the CodexSettings Folder without assuming its home, then add animator to the existing
[extensions].builtins list:
CODEX_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/lychd"
vi "$CODEX_DIR/lychd.toml"
Inscribe the provider anchors and inactive samples:
uv run --extra postgres-binary lychd init
The built-in animator extension registers runes/animator/portals/openai/ and
runes/animator/portals/google-gemini/. Both use an OpenAI-shaped HTTP interface, while the
Connector selects the declared provider's model-profile resolver. Selecting an animator/*
runtime also registers the shared PortalCloud Model base.
For another interface, an extension must supply its RuneService Config File schema and Connector factory. The schema
alone admits declarations, without constructing a runtime or capability. That construction needs
one exact PortalDefinition for the concrete schema; there is no anonymous OpenAI-compatible
fallback.
2. Seal one credential
Create exactly the name the RuneService Config File will reference; never put the value in TOML:
SECRET_NAME=portal_openai_main
read -rsp "Value for $SECRET_NAME: " LYCHD_SECRET
printf '%s' "$LYCHD_SECRET" | podman secret create "$SECRET_NAME" -
podman secret exists "$SECRET_NAME"
unset LYCHD_SECRET SECRET_NAME
For deliberate rotation, use podman secret create --replace, then recreate the VesselEngine Room.
3. Declare one model
Create "$CODEX_DIR/runes/animator/portals/openai/main.toml":
name = "openai-main"
description = "Explicit remote chat capability."
api_key_secret_name = "portal_openai_main"
probe = false
[[models]]
id = "gpt-5.2"
[models.capabilities]
families = ["chat"]
modalities_in = ["text"]
supports_tools = true
[models.generation]
max_tokens = 4096
The openai leaf supplies provider identity and its default URL. Override base_url only for an
OpenAI-compatible endpoint. A PortalCloud Model with no [[models]] blocks contributes no capability; LychD
does not infer or download a provider catalogue. The endpoint is a root: an existing path prefix is
kept when /models is appended, while embedded credentials, query or fragment state, port zero,
and out-of-range ports fail validation. Model ids are unique; duplicates fail before registry
construction.
PortalCloud Model models use the Pydantic AI profile selected by provider alias and model id, so settings
known to be unsupported are omitted rather than forced onto the request. OpenRouter, LiteLLM, and
Ollama retain their provider resolvers; Gemini's OpenAI-compatible leaf uses Google's model
profile. Generic compatible endpoints and local SoulstonesLocal Models use a conservative compatibility
profile. OpenRouter model ids keep their provider/model prefix. The current Google, LiteLLM, and
Ollama aliases reject the Responses surface; OpenAI, OpenRouter, and explicitly compatible generic
endpoints may select it. This is not evidence of a native Gemini transport.
4. Bind, restart, and observe
Restart only a quiescent VesselEngine Room
There is no complete active-run census or graceful drain command. Restarting fails work in
RUNNING or AWAITING_HARDWARE. Stop submissions and let visible runs settle; if continuity
is uncertain, do not restart.
The direct Systemd restart below is a separately chosen operator action under Reanimation’s limits and the separately authorized recovery plan. It bypasses OrchestratorStage Manager admission and lease drain. It is not a delivered CLI fallback: public stop still refuses an active Vessel.
uv run --extra postgres-binary lychd bind --dry-run
uv run --extra postgres-binary lychd bind
systemctl --user restart lychd-vessel.service
uv run --extra postgres-binary lychd status
After binding, distinguish the three observations. Bind verifies the RuneService Config File, named secret, and
atomic reconciliation of units. CLI status inspects the installation. Neither establishes a
provider call or lists its model capabilities.
To inspect registration, open http://127.0.0.1:7134/orchestrator/status in the same-host browser.
Under all_capabilities, find the row whose capability_key is openai-main:chat:gpt-5.2.
This row establishes that the declared
capability was synthesized and registered. Because the example sets probe = false, its phase
remains unknown.
A later warm observation would establish readiness of that exact declared binding, without
establishing egress eligibility or credentialed invocation. Current DispatcherTraffic Controller policy quarantines
every PortalCloud Model grant.
The BridgeChat has no provider picker. Once the general Egress GatePrivacy Filter is delivered, a future attributable
end-to-end proof may make this PortalCloud Model the only eligible chat plus tools candidate and send one
benign public-safe fixture through a fresh payload-bound decision. Today, do not send that prompt:
the current executable proof ends at declaration, bind, and readiness observation because
DispatcherTraffic Controller refuses the grant.
Failure and Closure
If the row is absent, check extension activation, the provider anchor, at least one model block, and the VesselEngine Room restart. If a request fails, inspect the VesselEngine Room journal and provider account separately; do not reinterpret passive warmth as a provider response.
Close the sky by removing its routable model declarations, binding the new intent, and restarting the quiescent VesselEngine Room. The named secret may then be rotated or retired under the operator's own secret policy.
Credential custody in Reach
Reach needs a stronger credential boundary than the current Vessel-local Connector supplies. Its deployment profiles must keep the provider secret out of both Reach core and the Discord edge, even when they share a host. The Designed profiles place that one exact provider or peer credential in a separate Provider Gate/egress adapter service, which accepts only typed, egress-admitted attempts.
Until that service boundary and its deployment receipt are delivered, the current Connector cannot serve as a Reach provider path, including in the public VPS profile.
Portal Rune Reference
| Field | Default | Meaning |
|---|---|---|
name |
required | AnimatorModel Runtime identity and capability-key prefix. |
description |
"" |
Operator note. |
provider_name |
provider leaf | Connector identity. |
base_url |
provider leaf | HTTP(S) endpoint root without credentials, query, fragment, or invalid port. |
api_key_secret_name |
null |
One option-free Podman secret name, never its value. |
models |
[] |
Explicit declarations; empty means zero capabilities. |
generation |
null |
Portal-wide generation overlay. |
probe |
false |
Opt in to the unauthenticated /models probe. |
Each model requires provider-facing id; it may add capability hints and a per-model
generation overlay. Operator description belongs to the PortalCloud Model, not each model block. Capability hints default to chat with text admission. Verification
may downgrade a declaration, never invent one.