VTRIP·景点门票查询
在本 Skill 目录执行一次查询,脚本生成结果页并返回回答素材:
node scripts/attraction-ticket-search.js --query "西湖门票多少钱" --output-dir "$PWD/outputs"
正常查询直接执行,凭据由脚本读取,不要阅读 scripts/。只有配置失败或用户要求排查时,才读取配置指引。
查询链路(脚本内自动完成,Agent 无需另调):
knowledge/search拉景点 POI(丢弃攻略/跟团游)- 单景点门票问句(问句含门票/票价/儿童票等,且能锁定某个带
poiId的景点):再调POST /api/agent/ticket/poi/detail/productsOpenSso拉该 POI 下可售商品树(成人/学生/儿童/套餐等),写入materials.products - 城市逛景点等非单点问句:对有参考价的 POI 走
listDetailOpenSso叠 SKU;商品接口失败时也回退这条 - 短链排版不变;失败时保留知识检索参考价
可选 --use-date YYYY-MM-DD(默认明天)。本地联调 Agent 可设 VTRIP_AGENT_BASE_URL=http://127.0.0.1:8000。
交付形态(固定,勿混用)
| 位置 | 内容 | 工具 |
|---|---|---|
| 对话正文 | 根据 materials 写的景点/门票推荐文字 |
直接输出 markdown |
| 对话底部 + 右侧内置浏览器 | card-html 结果页(自动打开预览 + artifact 卡片) | present_files 中的 htmlFile(本地路径) |
单文件交付:files: [htmlFile]。 只传本地 HTML 文件的绝对路径——宿主会自动在内置浏览器打开实时预览(获得焦点),同时在对话底部生成 artifact 卡片,一个路径同时覆盖两个入口,无需再传 htmlUrl。htmlUrl 仅是脚本内部短链服务地址,不得作为 present_files 参数传入。
不调用 present_files,用户看不到结果页;禁止用文字或正文链接代替。
成功时 stdout 被 WORKBUDDY_VISUAL_JSON_START / END 包裹,内含:query、counts、htmlFile、htmlUrl、previewHint、presentFiles、materials 等。
解析该 JSON 后,只做两步,然后立刻结束:
- 根据
materials写完对话回答(见下)。正文末尾写「完整清单与卡片详情见下方结果页」;不可只写推荐却不提结果页。不要把htmlFile/htmlUrl写成可点 markdown 链接(聊天里点 http 常进系统浏览器)。 - 必须
present_files({ files: presentFiles.files }),且files严格等于脚本返回的presentFiles.files。这是本轮最后一个工具调用;调用后零文字。
previewHint 为 file-card+browser-preview:本地 HTML 文件由宿主自动在内置浏览器打开并生成卡片,无需额外操作。
本地短链服务不可用时,materials 不带 shortUrl,正文相应名称标注「暂无详情」即可,交付方式不变。
materials 是扁平数组,每条 type 均为 poi。含名称、目的地、简介,以及实际存在的地址、时长、评分、标签、门票价、币种;空字段省略。linkable 表示有无可详情链接;有链接且本地服务可用时带 shortUrl(http://127.0.0.1:<端口>/r/<scope>/<序号>),不返回完整 url。
若该景点走过门票商品 / SKU 查询:
priceSource: "products":单景点商品树;products为{ category, ticketTitle, productName, price, currency, ... }。用户问儿童/学生/成人时优先写名称匹配的商品;没有匹配就说明「当前可售商品里未见儿童票」并列出最接近项(如学生票/亲子票)priceSource: "sku":price为可售最低价;skus为若干{ name, price, currency }priceSource: "reference"或搜了没货:仍用知识检索参考价useDate:本次查询的游玩日
HTML 按接口顺序展示全部可识别景点,不混入攻略或跟团游。智能体只用同次 materials 回答,不读 HTML、不另建中间文件。
回答按目的地与内容质量挑选,注意城市与州的区别,排除异地与重复。先概括有哪些景点,再写亮点;有 products 时按品类写出匹配的商品名与价格(儿童票优先写含「儿童」的商品);否则有 skus 写 SKU 价;再否则有 price 写参考价;都没有则不提票价。完整清单和详情留在结果页,不重复罗列。除非用户明确要求导出,否则不另建回答文件。
counts.poi === 0 时说「暂无相关景点结果」;有候选但均不相关时说「本次候选未筛选出相关结果」。不能只给文件链接或统计;也不能只写推荐却不在正文中表达结果页。
正文里景点名称,凡 materials 带 shortUrl 的,必须写成 markdown 超链接 [名称](shortUrl)。没有 shortUrl 的用普通名称并标注「暂无详情」。不要把完整长链接写进对话。完整清单仍留在结果页,不把全部条目都链进正文。
数据与权限边界
- 调用本 Skill 的
knowledge/search;单景点门票再调productsOpenSso,多景点/回退再调listDetailOpenSso;渠道固定ai_trip。脚本只保留知识检索返回的 POI,丢弃攻略与跟团游。脚本从环境变量或.env读取VTRIP_OPEN_API_KEY,放入X-Api-Key;不回显完整密钥。运行时配置读 Skill 根目录config.json,不存在则读config.example.json。 - 只引用素材支持的事实,不补写未返回的开放时间、预约政策、天气、最佳季节或人均消费。门票价优先
materials.products/priceSource=products,其次skus/priceSource=sku;否则才用知识检索参考价。没有价字段就不提价格。景点原始text中的促销票价不可引用;异常时长(如「30天」)忽略。 - 正文名称链接只用
materials.shortUrl;无短链标注「暂无详情」,不拼接详情地址或搜索页。输出目录按查询隔离,可能含签名参数,不公开上传。短链由本地服务 302 到接口详情页,空闲退出后失效。 - 知识检索失败就反馈错误,不编造结果,不用历史文件伪装本次成功。单条 SKU 查询失败不阻断整次查询。401/403 提示「Key 无效或未授权当前业务场景,请核对开放平台是否选择了配置中的业务场景」。进一步排查才读错误处理或接口约定。
- 无凭据时返回
status: requires_api_key,退出码 1,不生成 HTML。保留申请链接和返回的channelName(来自配置defaults.channelName)。读取配置指引,向用户完整展示三种配置方式(不要展示自检命令或脚本路径)。引导申请时必须说明:视旅开放平台共有 3 个业务场景(AI定制、AI商旅、VTRIPCLaw);本 Skill 的业务场景是返回的channelName;申请 API Key 时须确认已选择该场景,否则可能鉴权失败。配置完成后由 Agent 内部验证并重试原问题。 - 攻略、跟团游、综合「好玩的」(需攻略/商品)请使用旅游知识检索 Skill,不要用本 Skill 硬答。