本文档基于当前仓库实现(src/**、tests/**、.github/workflows/**、scripts/**)总结 NaviGo 的可解释与负责任 AI 实践。
每个 agent 在输出 Partial<PlannerState> 时都会追加一条 decisionLog 记录(makeDecisionLog),字段包括:
agentinputSummarykeyEvidenceoutputSummaryriskFlagstimestamp这意味着调用方不仅能看到最终 finalPlan,还能看到每一步“基于什么证据做了什么决策”。
需要 LLM 的 agent 都使用 withStructuredOutput(...) + Zod schema,避免自由文本直接进入状态:
ExtractedRequestSchema(requirement_parser)FormCompletionSchema(form_completer)RiskGuardSchema(risk_guard)PreferencesSchema(preference_agent)DestinationSuggestionsSchema / DestinationCandidateSchema(destination_agent)ItineraryDraftSchema(itinerary_agent)BudgetAssessmentSchema(budget_agent)PackingListSchema(packing_agent)PlanSynthesisSchema(plan_synthesizer)Zod 校验覆盖:
src/config/env.tssrc/interfaces/api/routes/plan.route.tsFinalPlanSchemapreference_agent 中,如果用户在 userRequest.interests 里明确给出了兴趣项,会覆盖模型抽取的兴趣,减少“模型擅自改写用户偏好”的风险。destination_agent 中,用户显式提供的目的地(hint + city code + IATA)会作为 fallback 候选前置,确保用户意图不被忽略。risk_guard 会把检测到的风险写入 safetyFlags(规则层 + LLM 语义层双重扫描)。budget_agent 超预算时写入 BUDGET_EXCEEDED。plan_synthesizer 会把安全标记带入最终输出。即使计划可继续生成,风险也不会被隐藏。
当检测到提示注入(BLOCKED_PROMPT_INJECTION)时,路由会直接进入 plan_synthesizer 生成安全拒答摘要,而不是继续执行完整规划链路。
form_completer 在缺少必填字段时,不会默默猜测或填充,而是生成 1–2 条自然语言澄清问题返回给客户端,由用户确认后再继续。这避免了模型擅自推断用户未明确表达的约束。
图状态使用 checkpointer 持久化,API 提供 GET /plan/:threadId 读取线程快照,可用于:
valuesLANGSMITH_TRACING=true 时启用 tracing;metadata 通过 buildTraceMetadata(...) 附带:
userIdthreadIdscenarioservice当前实现中,userRequest(包含 userId)属于 PlannerState 的一部分,因此会进入 checkpoint 状态(取决于所用 checkpointer)。
也就是说:
如果部署方有更严格的数据最小化要求,建议在调用前对 userId 做脱敏/映射,或在状态层引入最小字段策略。
以上边界均可从现有代码直接观察到。