首页Home 解决什么Solutions 产品能力Product 智能体编队Agents 技术架构Technology 工程深度Engineering 自我演化Self-evolution 行业场景Scenarios 运营透视Observability 信任与安全Trust
工程深度 · 怎么做到的Engineering depth · how it's done

真正的难度,不在能聊
靠得住

The hard part isn't chatting
it's being dependable

这一页是写给要把它放进生产环境的技术负责人的。别的页讲"能做什么",这一页只回答一个问题:当大模型会胡说、网络会抖动、进程会崩溃、而客户绝不能被打扰,这套系统凭什么靠得住。下面每一条都对应真实 Rust 代码里的函数与行号——可以拉着你的团队逐一核对,不是 PPT 话术。

This page is for the engineering lead who has to put it into production. Other pages cover features; this one answers one question: when the model hallucinates, the network flickers, processes crash, and customers must never be disturbed — why is this system dependable? Every item maps to a real function and line number — bring your team and verify, line by line. Not slideware.

可私有部署 · 不锁厂商Self-hostable · no lock-in 红线由 CI 强制Red lines enforced by CI 成本逐次可精算Per-call cost accounting 真实 file:line 可核对Real file:line, checkable
放进生产前,你会先问这三件事Before it ships, you'll ask these three

评估一套自治 AI,技术团队真正在意的

What an engineering team actually weighs in an autonomous AI

会被厂商锁死吗?
Will I be locked in?

可私有部署,模型自己选

Self-hostable, your model

对接的是 OpenAI 兼容协议,OPENAI_BASE_URL 一个环境变量就能指向自托管模型或任意兼容端点;运行时还能热切换 provider,不停机。代码、数据、模型都可以留在你自己的机房。

It speaks the OpenAI-compatible protocol; one env var, OPENAI_BASE_URL, points it at a self-hosted model or any compatible endpoint, with hot provider swap at runtime — no downtime. Code, data and model can all stay in your own datacenter.

config.rs:408 · llm.rs:1419 swap
红线靠谱吗,还是全凭自觉?
Are the red lines real, or honor-system?

承诺写进代码,CI 每次提交都扫

Promises compiled in, scanned every commit

"客户永远只跟 AI 对话""AI 永不自动核验知识""演化器碰不到生产"——这些不是文档里的承诺,是三道 CI 门禁:测试基线、红线词静态扫描、演化器隔离校验。任何一道挂了,提交进不来。

"Customers only ever talk to the AI", "the AI never self-verifies knowledge", "the evolver can't touch production" — not doc promises but three CI gates: a test baseline, a red-line static scan, and an evolver-isolation check. Fail one and the commit can't land.

check-baseline · check-no-human-takeover · check-evolution-isolation
跑起来花多少钱,说得清吗?
Can you account for the spend?

每一次模型调用都记账

Every model call is metered

每条运营有 token 与调用次数的硬预算,超额降级而不是失控烧钱;每一次模型调用单独落账,记 token、缓存命中、重试、延迟。成本能精确到每一次请求,不是月底一张看不懂的账单。

Each run has a hard budget on tokens and call count — overruns degrade instead of burning money; every model call is logged on its own with tokens, cache hits, retries and latency. Cost is accountable per request, not a mystery bill at month-end.

budget.rs · models.rs:2882 LlmCallLog
01把不稳定的大模型,驯服成生产级Taming an unreliable LLM into production

模型会胡说、会截断、会跑偏——这些都不该让客户看见

Models ramble, truncate and drift — the customer should never see it

大模型的输出天生不稳定:JSON 缺个逗号、长任务把正文塞进工具调用、网关半路掐断连接。我们没有把这些风险抛给客户,而是在客户端这一层用确定性代码逐一接住。

LLM output is inherently unstable: a missing comma in JSON, a long task that buries the answer in a tool call, a gateway that cuts the connection midway. We don't pass that risk to the customer — deterministic code at the client layer catches each case.

llm.rs:318 · parse_or_repair

三层 JSON 鲁棒解析

Three-layer JSON parsing

直接解析 → 确定性修复(补逗号、转义裸控制字符、拆单对象数组)→ 实在不行回喂模型修复,最多两次。一个标点不会毁掉整条运营。

Direct parse → deterministic repair (commas, raw control chars, singleton arrays) → as a last resort, hand it back to the model to fix, at most twice. One punctuation slip won't kill a run.

llm.rs:1153 · detect_tool_use_hijack

tool_use 劫持检测

tool_use hijack detection

某些模型在长任务里会先调工具,真正的答案跑进 tool_use block、正文只剩一句开场白。系统能识别这种"劫持"并给出明确诊断,而不是对着半句话硬解析。

On long tasks some models call a tool first — the real answer lands in a tool_use block while the text is just a greeting. The system detects this hijack and reports it clearly, instead of parsing half a sentence.

llm.rs:272 · with_format

传输层抗截断硬调优

Transport hardening vs. truncation

关连接池复用、强制 HTTP/1.1、开 TCP keepalive、绕代理——专治某些网关在 60 秒后静默截断 chunked 响应体的疑难杂症。这是真踩过的坑。

No pooled connections, forced HTTP/1.1, TCP keepalive, no proxy — a fix for gateways that silently truncate chunked bodies after 60s. A pothole we actually hit.

llm.rs:1049 · compute_backoff

退避带抖动 · 封顶 · 尊重 Retry-After

Backoff with jitter, cap & Retry-After

指数退避叠加 ±随机抖动、封顶 60 秒、并尊重服务端返回的 Retry-After。既防重试雪崩,也避免单次睡几十分钟撞上任务超时墙。

Exponential backoff with ±jitter, capped at 60s, honoring the server's Retry-After. Prevents retry storms and avoids a single multi-minute sleep slamming into the task timeout.

llm.rs:1026 · is_retryable_llm_error

可重试错误精确分类

Precise retryable-error classification

区分"瞬时不可达"(含 Cloudflare 520/522/524、body 解码失败)与"确定性失败"。JSON 格式错误不重试——重试只会再烧一次 token,结果一样。

Separates transient failures (incl. Cloudflare 520/522/524, body-decode) from deterministic ones. JSON errors are never retried — a retry just burns tokens for the same result.

budget.rs:112 · record_tool_call

运行预算双维硬上限

Dual-axis run budget

每条运营有 token 与工具调用两个维度的预算,在一把锁内原子校验并累加。超额触发降级(跳过改写、本地评审兜底),而不是把 5xx 抛给微信回调。

Every run has a budget on both tokens and tool calls, checked and incremented atomically under one lock. Overruns degrade gracefully (skip rewrite, local review) rather than throwing a 5xx at the WeChat callback.

02主动,但克制Proactive, but restrained

一条消息只发一次,而且像真人一样懂分寸

Send once, never twice — and with a human's sense of timing

私域里发错一条、发重一条、半夜连发三条,都是事故。发送链路上最不性感、却最值钱的工程,全在"不该发的时候忍住,该发的时候不重复"。

In private domains, a wrong send, a duplicate, or three messages at midnight are all incidents. The least glamorous, most valuable engineering on the send path is about holding back when it shouldn't fire, and never repeating when it does.

outbox.rs:399 · compute_synthetic_key

合成幂等键 · 按天去重

Synthetic idempotency key

每条发送算一把幂等键落唯一索引。连无源头的主动跟进、后台手滑双击"发送",也会用"账号+联系人+内容+当天"合成键挡住,同样内容当天只发一次。

Every send computes an idempotency key on a unique index. Even source-less proactive follow-ups or a double-clicked "send" are caught by an account+contact+content+day key — the same content goes out once per day.

gateway.rs:2752 · send_outbound_message

发出后落库失败 · 绝不重发

Post-send DB failure never resends

消息已经送到微信、但写本地库失败时,系统只记一条审计、绝不返回错误——因为返回错误会让派发器重试,把同一条消息再发给客户一次。宁可少记一笔,不能重发一条。

If a message reached WeChat but the local write failed, the system logs an audit and never returns an error — an error would make the dispatcher retry and resend. Better to miss a log than repeat a message.

outbox_dispatcher.rs:645 · mcp_already_succeeded

崩溃 / 超时后 · 先核对再补发

Post-crash delivery check

worker 崩了或 30 秒超时被回收时,补发前先查 MCP 调用日志确认上一次到底送没送达。送达了就直接标完成,不会因为一次崩溃让客户收到两条。

When a worker crashes or a 30s timeout reclaims the job, it first checks the MCP call log to see whether the previous attempt actually delivered. If so it marks done — a crash never yields a duplicate.

pacing.rs:15 · account_send_interval_ms

账号级最小间隔 · 反连珠炮

Per-account min interval

单个 worker 串行跨客户背靠背零间隔地发,是典型的机器特征。每条发送前查这个账号上次实发时刻,间隔不够就重排,并叠加随机抖动,像真人一样有呼吸。

One worker firing back-to-back across customers is a telltale bot signature. Before each send it checks the account's last actual send time, reschedules if too soon, and adds random jitter — the cadence breathes like a human.

gateway.rs:2982 · precheck_operation_policy

四道节制门

Four restraint gates

连续主动触达上限、必须等客户先回复、每日触达计数、策略冷却期——任何一道不满足就忍住不发。主动经营关系,但绝不变成骚扰。

A cap on consecutive proactive sends, "wait for the customer to reply first", a daily touch count, and policy cooldown — fail any one and it holds. Proactive about relationships, never spammy.

tasks.rs:33 · reclaim_stale_running_tasks

任务认领 · 超时回收 · 心跳续约

Claim, reclaim & heartbeat

任务用 CAS 原子认领,抢不到就跳过,杜绝多副本重复跑;卡死的任务超时自动回收重试,连续回收三次强制失败防死循环;长任务用心跳续约认领时间,不被误回收。

Tasks are claimed atomically via CAS — lose the race, skip it, no duplicate runs. Stuck tasks are reclaimed on timeout; three reclaims force a failure to break loops; long tasks renew their claim via heartbeat so they aren't reclaimed by mistake.

03知识库会自己变聪明Knowledge that gets smarter

不只是存知识,还会自己发现哪里缺、哪里旧

It doesn't just store knowledge — it finds what's missing and stale

检索准不准、知识新不新,决定了 AI 说得对不对。这一层的工程,是让知识库随真实业务反应自我打磨,而不是建好就僵在那里。

Retrieval quality and freshness decide whether the AI is right. The engineering here lets the knowledge base polish itself against real business feedback, rather than freezing the day it's built.

knowledge_agent.rs:1653 · RankKey

过期知识只降权 · 不剔除

Stale knowledge is down-ranked, not dropped

被取代的知识 ×0.1、过期的 ×0.5 乘进有效相关度,数学化压到队尾,而不是突然消失或污染答案。属性测试锁定了排序随时间的单调性。

Superseded knowledge ×0.1, expired ×0.5 fold into effective relevance — pushed to the tail, not vanished or polluting answers. A property test locks ranking monotonicity over time.

knowledge_agent.rs:1711 · classify_recall_outcome

"查了等于没查"自动转整改

Failed recalls become fix tickets

一次召回是"完全没命中"还是"翻了一堆却引用不上",会被自动归类成知识缺口信号,沉淀进离线整改队列。知识的短板自己浮出来。

Whether a recall "missed entirely" or "opened a lot but cited little" is auto-classified into a knowledge-gap signal and queued for offline remediation. Weak spots surface themselves.

gap_signals.rs:834 · refresh_usage_stats_and_confidence

置信度随真实成交换血

Confidence refreshed by real outcomes

知识的置信度按 30 天滑窗动态升降:被引用后带来正向成交就加分,引发拦截就扣分,沉默则按域配置衰减。不是靠人拍脑袋定高低。

Confidence floats on a 30-day window: cited then converted earns points, cited then blocked loses them, silence decays per domain config. Not a human's gut call.

structural_proposals.rs:25 · StructuralKind

结构化写 · 只产提案,不能自动删

Structural writes propose, never delete

拆分、合并、重分类、标记取代这些不可逆操作,结构体里根本没有"提交/落地/删除"字段——物理上就不允许 AI 自动改库,必须经人审。

Split, merge, reclassify, supersede — these irreversible ops have no "commit/apply/delete" field in the struct at all. The AI physically cannot mutate the base on its own; a human must review.

ingest_worker.rs:46 · run_one_round

自动摄取 · 条件 GET + 失败熔断

Auto-ingest with conditional GET & breaker

外部源自动增量抓取:用 If-None-Match / 304 跳过没变的内容、按计划节流,连续失败三次降级、七天不可达自动停扫。RSS 走解析器、HTML 启发式抽正文。

External sources are pulled incrementally: If-None-Match/304 skips unchanged content, schedule throttles, three failures degrade, seven days unreachable disables. RSS via a parser, HTML via heuristic extraction.

knowledge_agent.rs:69 · CATALOG_CANDIDATE_CAP

中文友好的进程内重排

CJK-friendly in-process re-ranking

明确不引入向量库这个部署负担,也绕开对中文不分词的全文索引,改用语言无关的 bigram 在进程内重排——中文私域照样避免"高相关却被静态截断"的漏召。

It deliberately avoids the deployment burden of a vector DB and the CJK-blind full-text index, re-ranking in-process with language-agnostic bigrams — so Chinese private domains still dodge "relevant but statically truncated" misses.

04记得住,也记得准Remembers — accurately

长期关系靠记忆,而记忆最怕被写脏

Long-term relationships run on memory — which must never be corrupted

"经营关系"听起来很软,落到工程上却是一组很硬的约束:并发写不能撕裂、没证据的猜测不能升格成事实、关键早期记忆不能被新观察挤掉。

"Nurturing relationships" sounds soft, but in engineering it's a set of hard constraints: concurrent writes mustn't tear, evidence-free guesses mustn't become facts, and key early memories mustn't be crowded out.

memory.rs:1316 · occ_memory_filter

记忆巩固 · 乐观并发控制

Memory consolidation with OCC

入站消息和后台巩固任务可能同时改同一份长期记忆。用版本号做乐观并发:输给并发写的一方不落地、转重试,绝不出现半新半旧的撕裂状态。

An inbound message and a background consolidation may edit the same memory at once. Optimistic concurrency on a version field means the loser doesn't commit and retries — never a half-old, half-new torn state.

memory.rs:964 · personality confidence

没证据 · 置信度强制归零

No evidence → confidence forced to zero

人格画像的每个维度,只要没有对话原文证据锚定,置信度一律被代码强制设为 0——绝不采信模型自己报上来的高置信。猜测就是猜测。

Every personality dimension without a quoted conversational anchor has its confidence forced to 0 by code — the model's self-reported confidence is never trusted. A guess stays a guess.

memory.rs:344 · compact + PBT

关键记忆 · 不被新观察挤掉

Key memories survive compaction

记忆压缩时,未被作废的核心事实强制保留,数组永不无界膨胀(核心≤6 / 近期≤10 / 弃用≤20)。两条属性测试守住"上限"和"保留性"两个不变量。

On compaction, non-deprecated core facts are forced to persist and arrays never grow unbounded (core ≤6 / recent ≤10 / deprecated ≤20). Two property tests guard the cap and retention invariants.

reaction.rs:85 · find_one_and_update

用户反应分析 · 原子 claim 锁

Reaction analysis claim lock

同一条客户消息被多个回调重复触发时,只有抢到原子锁的那一个能真正调模型分析,其余直接返回。杜绝重复扣费、重复结论。

When one customer message is fired by multiple callbacks, only the one that wins the atomic lock actually calls the model; the rest return. No double billing, no double conclusions.

models.rs:3723 · MemoryFactRepr

历史记忆 · 零停机平滑升级

Zero-downtime memory upgrade

老库里的纯字符串记忆,通过无标签联合类型在反序列化边界自动升级成结构化事实,与新格式共存。升级一套系统不需要先停机迁移数据。

Legacy plain-string memories auto-upgrade to structured facts at the deserialization boundary via an untagged union, coexisting with the new shape. Upgrading needs no data-migration downtime.

05崩溃了,也不丢一条记录Even a crash leaves a record

每一次决策、调用、发送,都查得到、对得上

Every decision, call and send is traceable and reconcilable

自治系统最让人不安的,是"它到底做了什么、为什么这么做"说不清。我们的答案是:在每一次模型调用之前就先落一条记录,哪怕后面超时、panic、解析失败,也留得下痕迹。

What unsettles people about autonomy is not knowing what it did or why. Our answer: write a record before the model is even called, so that even a later timeout, panic or parse failure still leaves a trail.

run_envelope.rs:362 · write_run_envelope_started

Run Envelope · 调用前先落记录

Run Envelope written before the call

每条运营在调模型之前就写下一条 started 记录,结束时更新终态;万一连这条都没匹配上,还有 upsert 兜底补插并发事件。崩溃也不会有"凭空消失的一次运行"。

Each run writes a "started" record before calling the model and updates the terminal state on finish; if even that doesn't match, an upsert fallback inserts it and emits an event. No run ever vanishes into thin air.

run_envelope.rs:274 · is_valid_lifecycle_transition

生命周期 · 闭集枚举 fail-closed

Closed-set lifecycle, fail-closed

运行状态是不可逆的闭集枚举,终态吸收、脏状态值写库前直接拒收。状态机本身就拒绝"人工接管"这类违反全自治定位的语义。

Run lifecycle is an irreversible closed-set enum with absorbing terminal states; dirty values are rejected before they reach the DB. The state machine itself refuses semantics that violate the fully-autonomous stance.

models.rs:2543 · AgentRunLog

运行日志 · 约 40 个维度

~40-field run logs

每条运营记录提示词版本、token 预算与实耗、调用次数、各阶段结果、降级原因、改写前后摘要。分阶段写入互不覆盖,复盘时一条 run 看到底。

Each run records prompt versions, token budget vs. spend, call counts, per-stage results, degradation reasons and pre/post-rewrite summaries. Staged writes don't overwrite each other — one run, fully legible.

models.rs:2882 · LlmCallLog

逐次调用 · 成本可精算

Per-call cost accounting

每一次模型调用都记 prompt / completion / 总 token、缓存命中与否、重试次数、延迟毫秒、最终状态。成本和性能可以精确到每一次请求。

Every model call logs prompt/completion/total tokens, cache hit or miss, retry count, latency in ms and final status. Cost and performance are accountable down to a single request.

models.rs:2492 · AgentDecisionReview

独立评审 · 带快照与反应回填

Independent review with snapshots

评审独立成档,存评分、公式拆解、用到的知识,外加行业配置 / 运行参数 / 上下文三份快照,再回填客户真实反应与评审误判信号——形成可复盘的闭环。

Reviews are filed independently with scores, formula breakdowns, knowledge used, plus three snapshots — domain config, runtime params, context — then backfilled with the customer's real reaction and reviewer-misjudgment signals. A closeable loop.

把它放进你自己的环境里验

Put it in your own environment and verify

能聊天的产品很多,靠得住的不多。这一页的每一条都对应真实代码里的函数与行号——可私有部署,模型、数据、代码留在你的机房,拉着你的技术团队逐条验。想看这些工程怎么串成一条完整的发送链路,去技术架构页;想看红线怎么写进代码、被 CI 强制,去信任与安全页。

Plenty of products can chat; few are dependable. Every item here maps to a real function and line number — self-host it, keep model, data and code in your datacenter, and verify with your team. To see how it forms one send path, visit Technology; to see red lines compiled in and enforced by CI, visit Trust.