房贷咨询同时涉及用户画像、贷款产品、月供计算和合规边界。LendingTree 将这些职责拆分给三个协同智能体,并部署在 Amazon Bedrock 上,借助 LangGraph 管理流程、Model Context Protocol(MCP)连接工具和数据,再配合 Amazon Nova 模型与内置护栏,构建了一个可以全天候提供个性化指导的生产级助手。
这类系统的关键不在于“让一个模型回答更多问题”,而在于把复杂金融流程拆成可检查、可路由、可审计的步骤。
三个智能体如何分工
根据公开摘要,这个助手由三个协调工作的智能体组成。一个合理的职责划分可以是:
- 用户理解智能体:识别用户目标、预算、收入、首付、信用状况和购房阶段,补齐缺失信息。
- 贷款分析智能体:根据结构化用户信息调用贷款产品、利率或月供计算工具,比较可能的方案。
- 指导与合规智能体:把分析结果转换为用户能理解的建议,检查敏感表述,并明确说明哪些内容需要人工贷款顾问或正式审批。
这里的重点是职责边界。计算月供的工具不应由负责自然语言表达的智能体随意改写参数;合规检查也不应只依赖模型“记住规则”。每个智能体都应有明确的输入、输出和可观测事件。
LangGraph 适合表达这样的状态流:收集信息、判断是否需要追问、调用工具、交给下一个智能体、执行护栏检查,然后生成回复。图中的每条边都可以记录原因,方便定位错误和复盘用户会话。
MCP 让工具接入保持独立
房贷助手通常需要接触多个外部能力,例如贷款产品目录、月供计算器、资格预估服务和客户资料系统。将这些能力直接写进提示词或某个智能体的私有代码,会让版本管理和权限控制变得困难。
MCP 可以把工具和上下文以统一协议暴露给智能体。这样,智能体关注“需要什么能力”,而工具服务负责参数校验、授权、日志和真实数据访问。对于金融场景,工具层还可以强制要求:
- 金额、利率和期限必须使用明确的数据类型和单位。
- 缺失或异常输入不能静默使用默认值。
- 返回结果必须带有数据时间或版本信息。
- 只读查询和会改变客户状态的操作使用不同权限。
- 敏感个人信息不得出现在普通调试日志中。
MCP 并不会自动解决安全问题。它只是规范了模型与工具之间的连接方式;真正的访问控制、数据脱敏、超时、重试和审计仍需要在服务端实现。
Amazon Nova 与护栏的组合
摘要指出,LendingTree 使用 Amazon Nova 模型,并配合内置护栏满足金融服务场景的严格合规要求。实际设计中,可以把模型能力和业务约束分成两层:
- 模型层负责理解问题、组织信息和生成自然语言。
- 护栏与业务服务层负责阻止不允许的内容、约束敏感主题、校验工具参数,并确保输出不会被误解为正式贷款承诺。
一条合规的回答通常需要同时满足几个条件:它基于当前可用数据,清楚区分估算与正式报价,不暗示审批结果,也不会因为用户追问而绕过限制。对高风险问题,系统应转人工或要求用户通过正式流程提交资料,而不是继续生成更肯定的猜测。
“24/7”解决的是可用性,不代表任何时间都可以给出确定的金融结论。系统仍需要处理数据过期、第三方服务不可用、模型拒答和人工接管等状态。
一个可改造的最小编排示例
下面的 Python 示例用标准库模拟三个智能体和一个 LangGraph 风格的状态流。它可以直接运行,用来理解路由和边界;生产实现中,应将 call_agent 替换为 Amazon Bedrock Runtime 调用,将 lookup_products 替换为受权限控制的 MCP 工具,并在模型调用前后接入实际护栏。
from dataclasses import dataclass, field
from typing import Any
@dataclass
class MortgageState:
user_text: str
profile: dict[str, Any] = field(default_factory=dict)
analysis: dict[str, Any] = field(default_factory=dict)
response: str = ""
handoff_required: bool = False
def call_agent(name: str, state: MortgageState) -> dict[str, Any]:
"""示例代理;生产环境可替换为 Bedrock + Amazon Nova 调用。"""
if name == "intake":
return {
"income": 120000,
"down_payment": 80000,
"loan_amount": 400000,
"term_years": 30,
}
if name == "analysis":
loan = state.profile["loan_amount"]
rate = 0.065
months = state.profile["term_years"] * 12
monthly_rate = rate / 12
payment = loan * monthly_rate / (1 - (1 + monthly_rate) ** -months)
return {"estimated_rate": rate, "estimated_payment": round(payment, 2)}
if name == "guidance":
payment = state.analysis["estimated_payment"]
return {
"text": (
f"根据示例输入,估算本金和利息月供约为 ${payment:,.2f}。"
"这不是贷款报价或审批结果,请通过正式流程确认。"
)
}
raise ValueError(f"unknown agent: {name}")
def guardrail(state: MortgageState) -> None:
"""生产环境应调用 Bedrock Guardrails 及业务合规规则。"""
forbidden = ("保证批准", "一定获批", "正式报价")
state.handoff_required = any(word in state.response for word in forbidden)
if state.handoff_required:
state.response = "该问题需要人工贷款顾问确认,请通过正式申请流程提交资料。"
def run_assistant(user_text: str) -> MortgageState:
state = MortgageState(user_text=user_text)
state.profile = call_agent("intake", state)
state.analysis = call_agent("analysis", state)
state.response = call_agent("guidance", state)["text"]
guardrail(state)
return state
if __name__ == "__main__":
result = run_assistant("我想了解 40 万美元、30 年期贷款的月供")
print(result.response)
print({"handoff_required": result.handoff_required})
运行方式:
python mortgage_orchestrator.py
改造为生产服务时,建议为每次执行生成 conversation_id 和 trace_id,记录智能体转移、工具名称、参数校验结果、护栏结果和人工接管原因。日志应避免直接写入完整收入、地址、社会安全号码等敏感信息。
从演示走向生产的检查清单
- 定义结构化状态:不要让下一个智能体只能从上一段自然语言中猜测金额和期限。
- 限制工具权限:只读查询、计算和客户状态变更分别授权。
- 处理不确定性:为过期利率、缺失数据、工具超时和模型拒答定义明确分支。
- 验证模型输出:使用 JSON Schema、数值范围检查和业务规则校验,而不是只检查 HTTP 状态码。
- 保留人工入口:复杂信用问题、投诉、歧视风险或用户要求正式报价时,应能快速转人工。
- 测试边界案例:包括多轮追问、单位混淆、极端金额、重复请求、提示注入和敏感信息泄露。
- 度量真实效果:关注信息补齐率、工具调用成功率、错误建议率、人工转接率和用户完成正式申请的比例。
多智能体架构适合职责差异明显、工具较多且需要审计的流程,但它也会增加延迟、调用成本和调试复杂度。较稳妥的落地路径是先把计算和数据访问做成确定性服务,再用 LangGraph 编排少量职责清晰的智能体,最后通过 Amazon Nova、MCP 和护栏逐步扩展覆盖范围。这样,模型负责提升交互质量,关键金融决策仍由可验证的规则和正式业务流程托底。