7. Installation acceptance
POC deployment manual chapter. Verified against the 2026.10 mainline; command output follows the installer delivered for that engagement.
Back to overview · Full table of contents · Download full PDF
This chapter answers one question: can the installed environment actually be used. Acceptance has four layers: host-side services are healthy; readiness states are understood; one real business call goes from the caller through the gateway to the model and back, and can be found in the console by request ID; the deny path rejects as expected and the error code can be read. All four layers, plus the record table in section 7.6, must be complete before the environment is handed to the customer to start the POC. The readers are the implementation engineer and the customer acceptor.
The installer's post-install acceptance (section 4.6) only proves that platform base services are usable. It does not mean models, authorization, and the business path are open. Acceptance in this chapter is judged by post-install acceptance result + zenova status + a real business call, not by what a direct hit on an internal port returns.
7.1 Host-side checks
Applies to: the first acceptance after install; also after every upgrade, every deployment-configuration change, and every host reboot.
Prerequisite: signed in to the install host as root; the install has printed complete and post-install acceptance has no blocking items.
Procedure
- Inspect each service's status and the current version.
# Install host · root · read-only
sudo zenova status- Inspect base services that do not start with
zenova-.zenova statuslists onlyzenova-services; the ones below must be checked with systemctl separately (an item not deployed by the installer shows the unit as missing, which is expected).
# Install host · root · read-only
systemctl status postgres clickhouse caddy secret-service spicedb --no-pager
systemctl status rustfs --no-pager # present only when object storage is Bundled object storage- Run a full doctor and save the report, then check the exit code.
# Install host · root · write (creates report files only under /root/zenova-install)
sudo zenova doctor --all --save /root/zenova-install/doctor
echo "doctor exit code: $?"- File the report and the
zenova statusoutput with the handover materials.
# Install host · root · write (creates files only under /root/zenova-install)
sudo zenova status --json > /root/zenova-install/status.json
ls -l /root/zenova-install/doctor* /root/zenova-install/status.jsonWhat you will see
zenova status: running state of eachzenova-service, current version, instances, and any in-progress or last upgrade. Slotted services such as the control plane, background worker, and runtime store show the slot currently taking traffic (for examplezenova-control-plane@a). Column names follow the actual output.- systemctl: every deployed unit shows
active (running)and is enabled at boot (enabled). zenova doctor --all: lists every check, including passed and skipped items. Failed items carry a stable diagnostic code (such asHOST_…,SVC_…) and a remedy. When the path after--savehas no extension, the report is saved as.txt.- Exit code:
0when there is no blocking item;2when there is a blocking item.
| doctor result | Meaning | Remedy |
|---|---|---|
| Exit code 0, no warnings | Host and connectivity are all healthy | Go to section 7.2 |
| Exit code 0, with warning items | Does not affect use; must be recorded | Record the warning items and diagnostic codes in section 7.6; confirm whether they are in this engagement's scope |
| Exit code 2 | There is a blocking item | Follow the diagnostic code and remedy in the report, then rerun. Code meanings are on the product documentation site's "Install and operations diagnostic codes" page |
Note: zenova start/stop/restart accept only service names that start with zenova-. postgres, clickhouse, caddy, secret-service, and spicedb are not started or stopped through the zenova command. When a service is not running, look at the logs first (section 8.5); do not restart repeatedly.
Note: to check connectivity to a model or tool address, add --target <URL> for layered DNS → TCP → TLS → HTTP checks. When the report notes "direct connect; may not match production egress", the result does not represent connectivity of the gateway egress.
7.2 Meaning of ports and readiness
Applies to: during acceptance, when you see 503, a column showing Not verified, or a service missing from zenova status. Check this table first, then decide whether to act.
Procedure
- For a phenomenon in the table below, use the Meaning column to decide whether it is a healthy state.
- If it is not a healthy state, go back to section 7.1 and locate it with
zenova statusandzenova doctor.
| Phenomenon | Meaning |
|---|---|
Readiness check on the central gateway-node data plane (3080) returns 503, reason no_tenant_routes | Expected. There is not yet a tenant, or model routing is not configured. Recovers after creating a tenant (section 6.3) and finishing model configuration in section 7.3 |
| For a few seconds after the control plane switches slot, the internal ingress returns 503 | Expected. The ingress proxy holds new requests for up to 5 seconds |
| The Model authenticity column in the Model providers list shows Not verified | Unrelated to health. In an offline environment verification cannot complete and stays Not verified |
zenova status does not show postgres, clickhouse, or caddy | Expected. It lists only zenova- services; the rest are inspected with systemctl status <name> |
| Agent container reachability in post-install acceptance shows "check not implemented" | Expected. That item is warning-level, not implemented in this release, and does not affect install completion |
| Gateway node health waits a long time | Expected. That item waits up to 150 seconds |
Listen-port boundaries:
| Port | Listen scope | May it be opened externally |
|---|---|---|
| Business-ingress port (default 80), 443 | All interfaces (or the bind NIC specified at install) | Yes; the installer has already opened them on Linux |
| Split-out admin-ingress port | Same | Open yourself per the customer's management-network rules; the installer does not open it |
| 3010, 3080, 3300, 3320, 3325 | All interfaces, for agent containers on this host to call back | Must not be opened externally |
| Other internal-service ports | Loopback only | Not involved |
What you will see: Listener boundary in post-install acceptance has passed; from the business network only the business ingress (and a split-out admin ingress) can be reached.
Note: do not judge whether the platform works by curling an internal port. Returns from internal ports depend on tenant, routing, and slot-switch state; 503 is often healthy. Whether it works is judged by the post-install acceptance result, zenova status, and the real business call in section 7.3.
Note: 3010, 3080, 3300, 3320, and 3325 listen on all interfaces so containers on this host can call back. The installer does not block them at the network boundary for you. On the host firewall or cloud security group, open only the ingress ports to the outside.
7.3 A real business call
Applies to: must be completed once before every POC environment is handed over. This is the only direct proof that "installed" means "usable".
Prerequisite: Chapter 6 is done (password change, two-factor, tenant created, license imported); you have a usable upstream model address and credentials; the tenant has a test member account (created under the tenant's Organization & access). Model providers, models, model groups, and availability are operated by the tenant administrator. Platform root has no tenant membership and cannot run a playground call.
Procedure
- Add a model provider. The tenant administrator opens Admin Console → Models → Model Providers, chooses Add model provider, selects the provider type, checks Request address and Model request format, fills in credentials, clicks Test connection and fetch models, Enables the models needed in the model table, and clicks Save model provider.
- Playground the model. Open Admin Console → Models → Models, open the Playground tab on the model just enabled, send one sentence, and confirm a success summary is returned.
- Add a model group. Open Admin Console → Organization & access → Model Groups, create a model group, fill in a name, add the model that just succeeded in the playground, and save.
- Authorize the test member. On that group's Availability and quotas tab, choose Edit availability, select the test member, set validity to Long-term or covering the POC period, and save.
- The test member creates an API key. The test member signs in, opens Capability center → Home → API Keys, chooses Create key, fills in a name, selects the model group authorized in the previous step and the billing owner, clicks Confirm, and immediately copies API Key (shown only this time). Administrators do not create keys for members in the console.
- Make a real call from a host on the business network.
# Host on the business network · ordinary user · write (produces one real call; it is billed)
export API_KEY='<test-member-API-key>'
curl -sS -i "<access-url>/api/v1/agent-gateway/openai/v1/chat/completions" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"<model-name>","messages":[{"role":"user","content":"hello"}],"max_tokens":32}'- Record
x-request-idfrom the response headers. An administrator opens the Gateway requests tab under Admin Console → Overview, searches by that request ID, opens the detail, and checks it. - Run the deny path, see section 7.4.
Base URLs for the three protocols (<access-url> is the access URL filled in at install):
| Protocol | Base URL | Auth header |
|---|---|---|
| OpenAI | <access-url>/api/v1/agent-gateway/openai/v1 | Authorization: Bearer <API-key> |
| Anthropic | <access-url>/api/v1/agent-gateway/anthropic | x-api-key: <API-key>; also accepts Authorization: Bearer |
| Gemini | <access-url>/api/v1/agent-gateway/gemini | x-goog-api-key: <API-key> or query ?key=; also accepts Authorization: Bearer |
What you will see
- Step 1: that provider's Available switch in the provider list is on; the Available models column shows the enabled models. After save, "saved; model routing will sync shortly" is expected.
- Step 3: a successful playground shows a summary like "OK · first token … · total … · … tok · …". On failure the page states whether it happened on this platform or on the provider side, and a Chinese reason keyed by the error code.
- Step 6: expected result is
HTTP/1.1 200, the body contains the model reply, and the response headers includex-request-id. - Step 7: Gateway requests can find the same call; model, result, duration, and token usage match this call.
- When the business side needs another protocol, call once with each Base URL in the table; expected results are the same.
Note: model in the request must be a model name in the model group bound to that key (the name from the model plaza or from GET <OpenAI Base URL>/models). Otherwise it returns 404; see section 7.4.
Note: playground and real calls are both billed. The most recent calls show Pending billing on the usage page; that is a short billing delay.
Note: when the delivery scope includes MCP services or API services, add one "fetch a tool list + one side-effect-free tool call" and record it as its own row in section 7.6.
Note: an API key is shown only once. After copying, store it in the test machine's secret management. Do not paste it into a ticket, instant message, or screenshot.
7.4 Deny path and error-code check
Applies to: immediately after the successful call in section 7.3. That the gateway "rejects what it should reject, and states why" is as important as "the call works".
Procedure
- Call once with a model name not in the availability scope: reuse the command in section 7.3, replacing
<model-name>with a model name that is not in the model group bound to that key. - Call once with a disabled key: the tenant administrator finds the test key on the API key management tab under Admin Console → Organization & access → Model Groups, opens the detail, and clicks Disable (the test member can also Revoke a key created only for this test under Capability center → Home → API Keys), then calls again with that key.
- (Optional) Call once after removing the test member from availability: Remove that member under Availability and quotas, then call again with a still-valid key.
- Record each time: HTTP status,
reasonandcodein the body, and response headersx-request-idandx-should-retry. - For rejects that can be tied to a member (steps 1 and 3), find the matching record in Gateway requests by
x-request-idand confirm the result is failure and the reason matches the response.
# Host on the business network · ordinary user · read-only (status line and key error-body fields only)
curl -sS -i "<access-url>/api/v1/agent-gateway/openai/v1/chat/completions" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"<model-name-not-in-this-group>","messages":[{"role":"user","content":"hello"}],"max_tokens":8}'The OpenAI-protocol error body looks like {"error":{"message","type","param","code","reason","request_id"}}, where reason is the stable error code (uppercase), code is the OpenAI-compatible code (lowercase), and request_id matches response header x-request-id. The Anthropic-protocol error body is {"type":"error","error":{"type","message","reason"},"request_id"}. The Gemini-protocol error body is {"error":{"code","message","status","details"}}, with code equal to the HTTP status.
What you will see (check against the product documentation site's Error reference page)
| Scenario | HTTP status | reason | code (OpenAI protocol) | Expected handling |
|---|---|---|---|---|
| Model name is not in the model group bound to the key | 404 | LLM_MODEL_NOT_AVAILABLE | model_not_found | Change the model name in the request |
| Key is disabled, revoked, invalid, or missing | 401 | commonly UNAUTHENTICATED; the exact reason in the 401 group follows the actual output | invalid_api_key | Check key status, expiry, and the auth header |
| Authenticated but not in availability, or authorization expired | 403 | PERMISSION_DENIED | permission_denied | The administrator checks availability and authorization validity |
| Content blocked by a guardrail | 403 | CONTENT_POLICY_BLOCKED | content_policy_violation | Adjust the content and retry |
| Quota pool exhausted | 429 | POOL_EXHAUSTED | insufficient_quota | The error text states the object, period, and recovery time; the administrator adjusts the quota |
| Hit a traffic-rule rate or concurrency limit | 429 | TRAFFIC_RATE_LIMITED, TRAFFIC_CONCURRENCY_LIMITED | rate_limit_exceeded | Retry later; if it persists, the administrator checks traffic rules |
| Upstream rate limited | 429 | LLM_RATE_LIMITED | rate_limit_exceeded | Retry later |
| Tenant monthly token cap exhausted | 402 | MONTHLY_TOKEN_EXCEEDED | insufficient_quota | The platform administrator Edit Quota under Tenants |
| Model routing not configured | 503 | MODEL_ROUTE_NOT_CONFIGURED | model_route_unavailable | The administrator checks the model provider, the model's upstream, and traffic-rule configuration |
| Traffic-protection circuit open | 503 | TRAFFIC_CIRCUIT_OPEN | circuit_open | Retry later; if it persists, the administrator checks traffic rules and the upstream |
| Upstream overloaded or unavailable | 503 | LLM_OVERLOADED, LLM_PROVIDER_UNAVAILABLE | server_is_overloaded, upstream_unavailable | Retry later |
| Upstream server error | 502 | LLM_UPSTREAM_SERVER_ERROR | upstream_server_error | Retry later |
This acceptance must produce the first two rows: step 1 expects 404 LLM_MODEL_NOT_AVAILABLE; step 2 expects 401 (code invalid_api_key). The remaining rows are states that may appear during the POC, listed so on-site staff can judge them.
Note: under the same HTTP status, different reason values are handled completely differently. For example 403 may be an availability problem (ask an administrator to authorize) or a guardrail block (change the content); 429 may be a quota pool exhausted (retry will not help; adjust the quota) or upstream rate limiting (retry later); 503 may be a circuit open, upstream overload, or model routing not configured. Always judge by reason, not by status code, and do not parse message text (message changes across versions and is usually English).
Note: whether a retry is worth it is in response header x-should-retry: true means wait per Retry-After and retry; false means a retry will not change the result.
Note: 401 means the gateway did not recognize the caller. Those requests may not be searchable by initiator in Gateway requests. For 401, record the response itself (status, reason, x-request-id); whether the console can find it follows the actual result. Authenticated rejects such as 404 and 403 should be findable by request ID.
Note: a Disabled key cannot be re-enabled in the console. Do not disable the key delivered to the customer in section 7.3. Use a key created only for this test on the deny path.
7.5 Optional-capability acceptance
Applies to: this install enabled capabilities beyond core. Accept only capabilities that were purchased and enabled this time. Capabilities the product does not include, that were not purchased, or that are not enabled are recorded as Not applicable in section 7.6.
Prerequisite: first check capability state under System maintenance › System Updates. Present on this host, not enabled means not enabled. License does not include this capability means the license does not cover it. Record both as Not applicable; do not enable them temporarily for acceptance.
Procedure
Check the table item by item.
| Capability | Zentrix Gateway | Full edition | How to accept | Expected result |
|---|---|---|---|---|
| Semantic cache | Ships with core | Ships with core | ① Under System Settings › Global settings › General › Default models, set Semantic-cache embedding model and Semantic-cache rerank model; both show In effect; ② Under Traffic → Traffic rules, add a Semantic cache action to a rule that does not specify a forward target; ③ Call twice with the same sentence, as an OpenAI Chat Completions single-turn request; ④ Open the second call's detail in Gateway requests | The second call's upstream segments show "semantic-cache hit; upstream was not requested"; usage shows two call kinds, Semantic-cache embedding and Semantic-cache rerank |
| Knowledge base | Optional (license must include knowledge base) | Optional | ① An administrator creates a knowledge base under Knowledge bases and sets a distribution target; ② A maintainer uploads a document and waits until status is Available; ③ On the library detail Retrieve tab, enter a keyword from the document | The just-uploaded content is hit and the original fragment can be viewed; a Knowledge base tab appears at the top |
| Document parsing | Not applicable (not in the Gateway edition) | Optional | Upload a PDF or Office document in a knowledge base | Document status becomes Available; retrieve hits the document body; a failed parse is labeled with the reason |
| Hosted agents | Not applicable (not in the Gateway edition) | Optional | Create an agent, publish it, and call it once in chat | The agent replies normally; detailed steps follow the full-edition user manual |
| Data high availability | Used on multi-host plans | Used on multi-host plans | Not involved in a single-host POC | Record Not applicable for a single-host POC |
What you will see
- Enabled capabilities show as enabled in the System Updates capability list.
- When the two semantic-cache models are not set, a rule that turns semantic cache on cannot be saved. When a model is unavailable or the call fails, the second call still goes to upstream, and the request detail states the reason, for example "not involved: semantic-cache embedding model unavailable".
- When saving the semantic-cache rerank model, the system actually calls that model with built-in samples and sets the hit threshold. A model that cannot tell synonymous from non-synonymous questions cannot be saved; choose another rerank model.
- Knowledge base: when the license does not include knowledge base or the deployment did not install it, the Knowledge base tab in Capability center and the Knowledge bases menu in the admin console are both hidden.
Note: semantic cache applies only to OpenAI Chat Completions format, a single user message (a system or developer message may also be present), and a single-turn request whose body is at most 256 KiB. When calling through the OpenAI-compatible ingress (/api/v1/agent-gateway/openai/v1/*), a request is neither read from nor written to cache if the rule chain has multiple forward targets or failover, a per-request token cap, a mounted plugin, response rewrite, output detection or request-header rewrite, or if an Application quota sits before content detection, a prompt, or request rewrite. Other rules that carry a quota, and rules that forward to a single named upstream, do not affect the cache. When a cache miss happens during acceptance, first look at the Semantic cache line under Request destination on the call detail Routing and rewrite tab. Semantic cache is a dynamic-routing license module; record Not applicable when the license does not include it. Deployments that use OceanBase as the platform database do not support semantic cache; record Not applicable.
Note: changing the knowledge-base embedding model rebuilds vector indexes for every document; semantic retrieve is paused during rebuild. Decide the embedding model before acceptance.
Note: hosted agents and document parsing need a container runtime. Only hosted agents need to grant the service user container-runtime rights, which is equivalent to root on the host. Obtain written consent from the customer security owner before enabling hosted agents (section 3.4).
7.6 Acceptance record
Applies to: fill in as you go through acceptance. When finished, both the implementing party and the customer sign, and the table is filed with the handover materials.
Procedure
- Fill in environment information first.
- Run each row and fill in Result:
Done,Not done(with reason and diagnostic code or reason),Not applicable. - For request rows, write
x-request-idin Result.
Environment:
| Item | Fill in |
|---|---|
| Product | Zentrix Gateway / full edition |
| Version (full) | |
| Platform and deployment form | |
| Enabled capabilities | |
| Access URL | |
| Install root | Default /opt/zenova |
| Data-dependency mode (PG / CH / object storage) | |
| License ID and expiry |
Acceptance items:
| Item | Method | Result | Recorder | Time |
|---|---|---|---|---|
| Post-install acceptance | Install completion output and Deployment configuration › Latest acceptance have no blocking items | |||
| Service status | sudo zenova status; every zenova- service is running | |||
| Base services | systemctl status for postgres, clickhouse, caddy, secret-service, spicedb (and rustfs) | |||
| Host doctor | sudo zenova doctor --all --save …, exit code 0; warning items recorded | |||
| Listener boundary | 3010/3080/3300/3320/3325 not opened externally; only ingress ports are external | |||
| Gateway node | office-primary online in the console | |||
| Model provider | Test connection and fetch models succeeded; models enabled | |||
| Model playground | Playground returned a success summary | |||
| Availability | Test member added under Availability and quotas | |||
| Member-created key | Test member created a key under Capability center → Home → API Keys | |||
| Real call (OpenAI) | curl returned 200 + a model reply; record x-request-id | |||
| Real call (Anthropic) | As needed; returned 200 | |||
| Real call (Gemini) | As needed; returned 200 | |||
| Call record | Gateway requests found the same call by request ID; model/result/duration/usage match | |||
| Deny: model not in scope | 404 LLM_MODEL_NOT_AVAILABLE; findable in the console | |||
| Deny: key disabled | 401, code invalid_api_key; record the actual reason | |||
| Deny: member removed from scope (optional) | 403 PERMISSION_DENIED | |||
| Tool call (when MCP / API services are in scope) | Fetch a tool list + one side-effect-free tool call | |||
| Semantic cache | Second same-sentence call shows "semantic-cache hit; upstream was not requested" | |||
| Knowledge base | Uploaded document status Available; retrieve hits | |||
| Document parsing | Gateway edition: Not applicable | |||
| Hosted agents | Gateway edition: Not applicable | |||
| Data high availability | Single-host POC: Not applicable | |||
| Operations notifications | Test message on the notification channel was received (record Not configured if none) | |||
| Off-host backup of key material | Section 8.1 done and registered | |||
| First platform backup | Section 8.2 done; record backup ID and off-host location |
Signatures:
| Role | Name | Signature | Date |
|---|---|---|---|
| Implementation engineer | |||
| Customer system administrator |
Note: any Not done row must state the reason, diagnostic code or reason, owner, and planned completion time; do not leave it blank. Rows that depend on a customer-external condition (upstream model egress, a license not yet issued) are Not done after stating the condition, not Not applicable.
Capability notes
| Not provided | Alternative |
|---|---|
| One command that completes end-to-end business acceptance | Post-install acceptance and zenova doctor cover only the platform and this host. Models, authorization, the call, and the deny path are completed by hand in the console and at the caller per sections 7.3 and 7.4 |
| An administrator creating an API key for a member in the console | The test member signs in and creates it under Capability center → Home → API Keys. An administrator can only search, rotate, disable, and delete |
| Judging whether the platform works from an internal port's return | Judge by post-install acceptance, zenova status, and a real business call (section 7.2) |
| Re-enabling a disabled key in the console | Create a new key to replace it; use a dedicated test key on the deny path |
| Platform root running a model playground | root has no tenant membership; playground as the tenant administrator |
| Agent container reachability post-install acceptance | This release shows "check not implemented", warning-level; check the matching capability with console functions per section 7.5 |
Previous: 6. First sign-in and initialization · Next: 8. Required post-install work and day-to-day operations
6. First sign-in and initialization
POC deployment manual chapter. Verified against the 2026.10 mainline; command output follows the installer delivered for that engagement.
8. Required post-install work and day-to-day operations
POC deployment manual chapter. Verified against the 2026.10 mainline; command output follows the installer delivered for that engagement.