Skip to content

Server Configuration ​

This document is a startup and configuration guide for the server, focusing on answering three questions:

  1. How to start it (local / cloud / desktop forms)
  2. Whether a public network is required (Conclusion: the server itself does not need it; only the REST API needs it when required)
  3. How to configure cloud access (connect to the Rust gateway to enable remote management)

Prerequisites ​

ItemRequirement
Node.js≥ 18.17 (20+ recommended)
Model API KeyOpenAI-compatible endpoint (DeepSeek / OpenAI / Ollama / custom)
(Optional) Cloud accountSelf-hosted Rust gateway + Hub, or use a managed service
(Optional) QQ Open Platform botRegister at q.qq.com
bash
# 获取代码并安装依赖
pnpm install

# 交互式配置(推荐):LLM 必配,QQ/邮件可选、可跳过
bash scripts/configure-server.sh

# 或手动:复制模板后填写
# cp .env.example .env

Environment Variables Overview ​

Write to .env in the project root (or export before startup):

VariableDescriptionDefault
DATA_DIRData/tenant root directory./.zqagent_data
PORTREST listening port8787
HOSTListening address (set to 0.0.0.0 for public deployment)127.0.0.1
WORKSPACEAgent workspace directoryCurrent directory
APPROVAL_TIMEOUT_SECONDSApproval/question pending timeout900
MAX_ITERATIONSMaximum iterations per turn800
OPENAI_API_KEY / OPENAI_BASE_URL / OPENAI_MODEL / OPENAI_REASONING_EFFORTModel configuration (if OPENAI_MODEL is unset, no model is specified and you need to select it in the console)—
TENANT_ID / TENANT_API_KEY / MODELDemo tenant automatically created on first startupdemo / Randomly generated on first startup / Default model
SECRET_KEYMaster key for encrypting notification credentials and similar dataAutomatically generated
FLEET_TOKEN / FLEET_SECRET / FLEET_GATEWAY_URLCloud access (usually automatically written to fleet.json when linking with a registration code)—
QQ_BOT_APP_ID / QQ_BOT_APP_SECRET / QQ_BOT_SANDBOXQQ bot (enabled after configuration)—
CONTEXT_WINDOW / COMPACTION_THRESHOLD_PCT / COMPACTION_CAP_TOKENSLong-conversation compaction parametersAutomatic

Once SECRET_KEY is set, it is recommended to keep it fixed for the long term: it is used to encrypt tenant signing keys and notification channel credentials. Changing it will invalidate the keys and credentials of old tenants.

Three Deployment Forms ​

bash
# 最小可运行(先确认能启动、能对话)
pnpm run server
# 日志:
#   zqagent server 监听 http://127.0.0.1:8787
#   已创建演示租户: id=demo apiKey=zk_xxxx(随机生成) model=...

# 完整远程控制(配好 .env 后):
#   FLEET_GATEWAY_URL=wss://gw.example.com/ws
#   QQ_BOT_APP_ID=...  QQ_BOT_APP_SECRET=...
#   OPENAI_API_KEY=sk-... OPENAI_MODEL=...
pnpm run server

After startup, verify that the service is available:

bash
# 演示租户 apiKey 首次启动随机生成并打印在启动日志里,取出来存进 TOKEN
TOKEN=<启动日志中的 apiKey>   # 形如 zk_1f0c...
curl -s http://localhost:8787/healthz     # => {"status":"ok"}
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8787/api/v1/sessions

Cloud Deployment (When Public REST Access Is Required) ​

Rent a cloud server and set HOST=0.0.0.0 to expose the port.

bash
# 推荐用 pm2 常驻
npm install -g pm2
HOST=0.0.0.0 pm2 start "pnpm run server" --name zqagent-server

# 安全建议:只对需要的人开放。若 REST 仅自己用,建议不直接暴露公网,
# 改用内网穿透,或用云服务器防火墙限制来源 IP。

Desktop Application (macOS / Windows) ​

The desktop app automatically starts the server locally; no manual startup is required. See Desktop App.

Three Options When Public REST Access Is Required ​

OptionApproachApplicable When
A. Intranet tunneling (recommended for individuals)Cloudflare Tunnel (free) or frp/ngrok, mapping a local port to public HTTPSHome/intranet machines, no need to rent a server
B. Cloud serverDeploy directly to a VPS, HOST=0.0.0.0Have an existing server, or need long-term stability
C. Do not use RESTUse the full gateway path (credentials issued by the control plane), and use REST only on your own computerDo not want to expose any port at all

Cloud Access (Rust Gateway) ​

Once connected, you can remotely manage this node from any device. The node only needs an outbound connection to the gateway (wss://, usually over 443); no public inbound access, no open ports, and no MQTT broker are required.

Create a one-time registration code in the user center (Hub), then run the following on the node machine:

bash
zqagent link --hub https://hub.example.com --code <注册码>
  • If a service is already running on the local machine → hot connect (no restart required);
  • Otherwise, credentials are written to {DATA_DIR}/fleet.json, and the next zqagent serve will connect automatically.

Option 2: Manual Configuration ​

bash
# .env
FLEET_TOKEN=<高熵随机>          # 命名空间标识
FLEET_SECRET=<高熵随机>         # 签名密钥(须与网关侧一致)
FLEET_GATEWAY_URL=wss://gw.example.com/ws
SECRET_KEY=<64位hex>           # 强烈建议显式设置

Verify after startup:

bash
curl -s -H "Authorization: Bearer $ADMIN_API_KEY" \
  http://localhost:8787/api/v1/fleet/pairing
# => {"data":{"gatewayUrl":"wss://gw.example.com/ws","fleetToken":"...","fleetSecret":"...","nodeId":"..."}}

Success is indicated when the startup log shows “Cloud access: wss://… (node nodeId)” .

Not Connecting to the Cloud ​

If no FLEET_* is configured, it is a purely local node: all local features work as usual, but the cloud cannot see it. You can run zqagent link at any time to connect.

For gateway-side deployment (keys, TLS, multiple replicas), see the repository’s docs/rust-gateway-plan.md and deploy/k8s/gateway/. For protocol details, see docs/wire-protocol.md.

Troubleshooting Common Issues ​

SymptomTroubleshooting
Node cannot connect to the gatewayConfirm the address is wss://.../ws; the certificate is issued by a CA (not self-signed); the firewall allows 443
Log says “Failed to connect to gateway”Check the reachability of FLEET_GATEWAY_URL and whether FLEET_SECRET matches the gateway
Server does not listen externallyHOST defaults to 127.0.0.1; for public access, set HOST=0.0.0.0 and allow the port
QQ gateway connection failsCheck AppID/Secret; whether intents permissions have been applied for; use QQ_BOT_SANDBOX=1 for sandbox
Emails cannot be sentFor QQ Mail, use an authorization code (not the login password); secure must match the port (465→true, 587→false)
Credentials invalid after changing SECRET_KEYSECRET_KEY should be fixed; changing it invalidates all credentials of old tenants