find_agent 工具能力与接口 PRD
文档版本:v1.0
代码基线:2026-08-03
文档性质:As-Is 工具产品说明与接口契约
适用对象:产品、算法、Agent Prompt、后端、测试与运维人员
1. 文档目标
本文说明“寻找视频 Agent”find_agent 当前真实可调用的工具,包括:
- 工具清单、定位和推荐调用阶段;
- 每个工具对模型暴露的参数 Schema;
- 参数的业务含义、默认值、枚举、数量限制和组合规则;
- 成功、部分成功和失败时的返回结构;
- 搜索、详情、画像、候选更新和运行结束之间的数据衔接;
- 当前接口限制、风险和验收口径。
本文以运行时 create_find_agent().tools 生成的 Schema 和当前实现代码为准,不把仅为旧调用方
保留、但未注册给 Agent 的函数算作可用工具。
2. 产品定位
find_agent 面向一条已经分级并完成视频点位拓展的需求,使用多个抖音数据来源完成:
- 搜索候选视频;
- 保存每次搜索及其候选;
- 拉取视频详情和受众画像;
- 判断相关性
R、老年受众倾向 E、分享价值 S 和综合价值 V;
- 将候选放入
primary 或 rejected;
- 完成运行并输出
goal_met、partial 或 no_match。
工具服务于模型的 ReAct 决策,但搜索记录、证据、候选门禁和最终运行结果均由代码持久化,
不能只依赖模型最终文本。
3. 工具总览
Agent 初始化后共有 13 个可调用工具:1 个框架内置工具和 12 个 find_agent 专属工具。
| # |
工具 |
类型 |
主要用途 |
是否写库 |
| 1 |
load_skill |
框架内置 |
按名称加载 Skill 指令 |
否 |
| 2 |
batch_search_and_record |
批量搜索 |
一次提交最多 6 个关键词任务,每项最多 2 页 |
是 |
| 3 |
douyin_search |
关键词搜索 |
使用内部搜索源获取一页视频 |
是 |
| 4 |
douyin_search_tikhub |
关键词搜索 |
使用 TikHub 获取一页视频和完整分页状态 |
是 |
| 5 |
douyin_user_videos |
作者扩展 |
按作者 sec_uid 获取一页最热或最新作品 |
是 |
| 6 |
douyin_detail |
详情证据 |
批量获取视频详情;新模式自动保存证据并重算门禁 |
新模式是 |
| 7 |
get_content_fans_portrait |
单条画像 |
获取视频点赞用户画像 |
否 |
| 8 |
get_account_fans_portrait |
单条画像 |
获取作者粉丝画像 |
否 |
| 9 |
batch_fetch_portraits |
批量画像 |
批量获取视频/作者画像;新模式自动保存并重算门禁 |
新模式是 |
| 10 |
normalize_age_portraits |
证据处理 |
将两侧年龄桶标准化为统一证据 |
否 |
| 11 |
batch_update_video_discovery_candidates |
候选决策 |
按 candidate_id 更新评分、理由和最终分池 |
是 |
| 12 |
update_video_discovery_run_status |
运行控制 |
更新运行状态、意图摘要和停止原因 |
是 |
| 13 |
query_video_discovery_state |
状态查询 |
读取运行、搜索轨迹和候选快照 |
否 |
以下文件存在,但当前没有注册给 find_agent:
create_video_discovery_run:运行由调度器在模型循环前预创建;
qwen_video_analyze:当前不开放视频理解;
batch_save_video_candidate_evaluations、audit_video_discovery_run 等旧接口:不在实际工具表中。
4. 推荐调用链
flowchart LR
A["调度器预创建 run_id"] --> B["批量或单页搜索"]
B --> C["返回 search_id 和 candidate_id"]
C --> D["douyin_detail 拉详情"]
D --> E["batch_fetch_portraits 拉双侧画像"]
E --> F["候选 R/E/S/V 判断"]
F --> G["batch_update... 写入分池"]
G --> H["query... 核对最终状态"]
H --> I["update... status=finished"]
I --> J["输出业务结果"]
推荐优先使用带 run_id + candidate_ids 的详情和批量画像新模式。该模式由工具从数据库读取
aweme_id 和作者 ID,自动保存原始证据、刷新候选字段并重算门禁,减少模型搬运大 JSON 的错误。
5. 全局接口约定
5.1 返回值类型
所有工具在 Python 层都返回 str。除 load_skill 成功时返回 Skill 上下文文本外,其余工具
返回值均为 JSON 字符串,调用方必须先解析 JSON,不能把它当成已经反序列化的对象。
通用成功字段通常包括:
| 字段 |
类型 |
含义 |
title |
string |
结果标题,主要用于日志和模型阅读 |
output |
string |
人类可读摘要,不是最终业务事实的唯一来源 |
通用错误字段:
| 字段 |
类型 |
含义 |
error |
string |
参数、上游接口、网络或数据库错误文本 |
input_error |
boolean,可选 |
true 表示调用参数错误;缺失不代表成功 |
title |
string,可选 |
错误场景标题 |
errors |
array,可选 |
批量调用中的逐项错误 |
框架通过返回内容中是否存在错误字段识别工具错误,但不会自动重试、回滚整条 Agent 运行或切换
备用工具。模型必须读取返回结果后决定下一步。
5.2 核心 ID
| ID |
来源 |
用途 |
约束 |
run_id |
调度器预创建 |
贯穿一次需求的视频发现过程 |
所有写库工具必须复用同一个值 |
search_id |
搜索工具返回 |
标识一页搜索记录 |
翻页/标签/作者扩展可作为 parent_search_id |
candidate_id |
搜索工具返回 |
标识一次搜索命中的候选记录 |
详情、画像、评分和分池更新的首选主键 |
aweme_id / content_id |
抖音内容 |
标识视频本身 |
同一视频被多个搜索命中时可对应多个 candidate_id |
author.sec_uid / account_id |
搜索或详情结果 |
标识抖音作者 |
作者画像及作者作品扩展使用完整 sec_uid |
5.3 当前 Schema 能力边界
工具框架可从 Python 类型注解生成顶层 JSON Schema,但当前不生成枚举、取值范围、字符串格式,
也不展开 list[dict] 内部对象字段。因此模型可见 Schema 中:
searches 和 items 只显示为“对象数组”;
source_type、status、排序方式等只显示为普通字符串;
- 单批上限、字段组合关系只存在于工具描述和运行时代码校验中。
本文后续表格补齐这些语义约束,但它们尚未全部成为可被模型供应方提前校验的 JSON Schema。
6. 搜索类工具
6.1 batch_search_and_record
功能
顺序执行多个关键词搜索任务。每完成一页立即新增搜索记录,并为该页每条有效结果新增候选。
适合启动阶段一次性提交 2~3 个语义不同的根搜索,也可用于受控翻页。
顶层参数
| 参数 |
类型 |
必填 |
默认 |
说明 |
run_id |
string |
是 |
- |
预创建的运行 ID,不能为空 |
searches |
array
| 是 |
- |
搜索任务数组,必须非空,最多 6 项 |
searches[] 对象
| 字段 |
类型 |
必填 |
默认/取值 |
说明 |
keyword |
string |
是 |
- |
实际搜索词,不能为空 |
query_reason |
string |
是 |
- |
为什么执行该搜索,不能为空 |
source_type |
string |
是 |
demand / seed / point / tag / pagination / mixed |
搜索来源类型 |
provider |
string |
否 |
internal_keyword |
可选 internal_keyword、tikhub |
max_pages |
integer |
否 |
1 |
自动限制到 1~2;超范围不会报错而会被截断 |
cursor |
string 或 integer |
否 |
内部源为 "0",TikHub 为 0 |
起始游标 |
search_id |
string |
否 |
"" |
TikHub 翻页状态,不是数据库 search_id |
backtrace |
string |
否 |
"" |
TikHub 翻页回溯状态 |
source_value |
string |
否 |
null |
来源值,如点位文本、标签词 |
parent_search_id |
integer |
否 |
null |
父搜索页的数据库 ID |
content_type |
string |
否 |
视频 |
传给底层搜索源 |
sort_type |
string |
否 |
综合排序 |
传给底层搜索源 |
publish_time |
string |
否 |
不限 |
发布时间筛选 |
filter_duration |
string |
否 |
不限 |
仅 TikHub 使用 |
min_duration_seconds |
integer |
否 |
30 |
实际最小值固定不低于 30 秒 |
返回结果
| 字段 |
类型 |
说明 |
title |
string |
固定为“批量搜索并自动落库” |
run_id |
string |
本次运行 ID |
task_count |
integer |
通过顶层校验并进入结果的任务数;不一定等于输入项数 |
saved_page_count |
integer |
已成功持久化的搜索页数 |
new_candidate_count |
integer |
所有成功页新增候选总数 |
error_count |
integer |
任务校验或分页执行错误数 |
errors |
array
| 带任务下标、关键词和页码的错误摘要 |
tasks |
array
| 各搜索任务的执行结果 |
tasks[].index |
integer |
原始输入数组下标 |
tasks[].keyword |
string |
搜索词 |
tasks[].provider |
string |
实际搜索源 |
tasks[].pages |
array
| 各页结果 |
pages[].page_no |
integer |
页码 |
pages[].results_count |
integer |
该页结果数 |
pages[].has_more |
boolean |
是否还有下一页 |
pages[].next_cursor |
string 或 integer |
下一页游标 |
pages[].search_id |
integer |
数据库搜索记录 ID |
pages[].new_candidate_count |
integer |
该页新增候选数 |
pages[].candidates |
array
| 该页候选摘要,结构见 6.5 |
pages[].persisted |
boolean |
是否成功落库 |
pages[].error |
string/null |
该页错误 |
output |
string |
批量结果摘要 |
error |
string,可选 |
所有页均未成功保存时出现 |
执行是串行的,不并发。单个任务某页报错后停止该任务后续翻页,但会继续处理后面的任务;因此
返回结果可能是部分成功。
6.2 douyin_search
功能
通过内部关键词搜索源获取一页抖音视频,并自动保存搜索页、原始搜索证据和候选记录。
参数
| 参数 |
类型 |
必填 |
默认 |
说明 |
run_id |
string |
是 |
- |
运行 ID |
keyword |
string |
是 |
- |
搜索词 |
query_reason |
string |
是 |
- |
搜索原因 |
source_type |
string |
是 |
- |
可选 demand/seed/point/tag/author/pagination/mixed |
source_value |
string/null |
否 |
null |
来源原值 |
parent_search_id |
integer/null |
否 |
null |
父搜索记录 ID |
page_no |
integer |
否 |
1 |
小于 1 时按 1 保存;大于 1 自动改为 pagination |
content_type |
string |
否 |
视频 |
上游支持 视频/图文 |
sort_type |
string |
否 |
综合排序 |
上游支持 综合排序/最新发布/最多点赞 |
publish_time |
string |
否 |
不限 |
上游支持 不限/一天内/一周内/半年内 |
cursor |
string |
否 |
"0" |
翻页游标 |
account_id |
string |
否 |
771431222 |
内部搜索接口账号 ID |
min_duration_seconds |
integer |
否 |
30 |
客户端短视频过滤阈值,实际不低于 30 秒 |
timeout |
number/null |
否 |
null |
请求超时;null 时底层默认 60 秒 |
返回结果
成功后返回“搜索页公共结构”,见 6.5。内部源特有或常用字段还包括:
| 字段 |
类型 |
说明 |
title |
string |
抖音搜索: {keyword} |
output |
string |
含标题、作者、点赞、评论、分享的文本摘要 |
filtered_count |
integer |
因时长不足被过滤的数量 |
duration_ms |
integer |
上游调用耗时 |
6.3 douyin_search_tikhub
功能
使用 TikHub 独立搜索源获取一页抖音视频,提供收藏、播放、话题以及完整分页状态,并自动落库。
参数
| 参数 |
类型 |
必填 |
默认 |
说明 |
run_id |
string |
是 |
- |
运行 ID |
keyword |
string |
是 |
- |
搜索词,不能为空 |
query_reason |
string |
是 |
- |
搜索原因 |
source_type |
string |
是 |
- |
可选值同单页内部搜索 |
source_value |
string/null |
否 |
null |
来源原值 |
parent_search_id |
integer/null |
否 |
null |
父搜索记录 ID |
page_no |
integer |
否 |
1 |
大于 1 自动记录为 pagination |
content_type |
string |
否 |
视频 |
不限/视频/图片/图文/文章,也兼容 0/1/2/3 |
sort_type |
string |
否 |
综合排序 |
综合排序/最多点赞/最新发布,也兼容 0/1/2 |
publish_time |
string |
否 |
不限 |
不限/一天内/一周内/半年内,也兼容 0/1/7/180 |
cursor |
integer |
否 |
0 |
首次为 0;翻页原样使用上次 next_cursor |
filter_duration |
string |
否 |
不限 |
不限/一分钟内/1-5分钟/5分钟以上,兼容供应商代码 |
search_id |
string |
否 |
"" |
供应商分页状态;翻页必须原样回传 |
backtrace |
string |
否 |
"" |
供应商回溯状态;翻页必须原样回传 |
min_duration_seconds |
integer |
否 |
30 |
客户端二次过滤,实际不低于 30 秒 |
timeout |
number/null |
否 |
null |
null 时默认 60 秒 |
返回结果
除 6.5 的搜索页公共结构外,还返回:
| 字段 |
类型 |
说明 |
provider |
string |
tikhub |
request_params |
object |
传给 TikHub 的规范化请求参数 |
filtered_count |
integer |
被时长过滤的数量 |
provider_search_id |
string,可选 |
供应商返回的分页 search_id;避免与数据库 search_id 混淆 |
backtrace |
string |
下一页回传值 |
duration_ms |
integer |
上游调用耗时 |
分页时必须同时复用上一页的 next_cursor、provider_search_id 和 backtrace。数据库
search_id 只能用于父子搜索关系,不能作为 TikHub 的供应商分页参数。
6.4 douyin_user_videos
功能
按作者完整 sec_uid 获取一页最热或最新作品,适合从高潜作者扩展更多候选;结果自动落库。
参数
| 参数 |
类型 |
必填 |
默认 |
说明 |
run_id |
string |
是 |
- |
运行 ID |
account_id |
string |
是 |
- |
作者 sec_uid |
query_reason |
string |
是 |
- |
作者扩展原因 |
source_value |
string/null |
否 |
null |
缺省时使用 account_id |
parent_search_id |
integer/null |
否 |
null |
触发作者扩展的父搜索页 ID |
page_no |
integer |
否 |
1 |
页码 |
sort_type |
string |
否 |
最热 |
仅支持 最热、最新 |
cursor |
string |
否 |
"" |
作者作品分页游标 |
min_duration_seconds |
integer |
否 |
30 |
实际不低于 30 秒 |
timeout |
number/null |
否 |
null |
null 时默认 60 秒 |
返回结果
使用 6.5 的搜索页公共结构,并保留:
| 字段 |
类型 |
说明 |
account_id |
string |
作者 sec_uid |
sort_type |
string |
实际排序方式 |
filtered_count |
integer |
被时长过滤的数量 |
duration_ms |
integer |
上游调用耗时 |
持久化返回前会移除原始 user_videos 和 search_results 大数组,只保留数据库生成的候选摘要。
6.5 搜索页公共返回结构
三个单页搜索工具成功持久化后共同返回:
| 字段 |
类型 |
说明 |
run_id |
string |
运行 ID |
search_id |
integer |
数据库搜索页 ID |
keyword |
string |
本页搜索词;作者作品为 author:{account_id} |
query_reason |
string |
搜索原因 |
source_type |
string |
实际保存的来源类型 |
source_value |
string/null |
来源值 |
parent_search_id |
integer/null |
父搜索页 ID |
provider |
string |
internal_keyword / tikhub / internal_blogger |
provider_state |
object |
保存的供应商分页状态 |
content_type |
string |
内容类型 |
sort_type |
string |
排序方式 |
publish_time |
string |
发布时间筛选 |
cursor |
string |
本页请求游标 |
page_no |
integer |
规范化页码 |
results_count |
integer |
上游本页结果数 |
new_candidate_count |
integer |
本页实际新增候选数 |
has_more |
boolean |
是否有下一页 |
next_cursor |
string 或 integer/null |
下一页游标 |
status |
string |
success 或 failed |
error_message |
string/null |
持久化的搜索错误 |
raw_evidence_id |
integer/null |
原始搜索证据 ID |
candidates |
array
| 本页新建候选摘要 |
persisted |
boolean |
成功落库时为 true |
candidates[] 摘要字段:
| 字段 |
类型 |
说明 |
candidate_id |
integer |
后续详情、画像和更新使用的数据库 ID |
search_id |
integer |
所属搜索页 |
aweme_id |
string |
抖音视频 ID |
title |
string/null |
标题或描述 |
author_name |
string/null |
作者名 |
author_sec_uid |
string/null |
作者完整 sec_uid |
publish_at |
string/null |
发布时间 |
duration_seconds |
number/null |
视频时长,秒 |
share_count |
integer/null |
分享数 |
gate_status |
string |
初始通常为 pending |
相同 aweme_id 被不同搜索命中会创建不同 candidate_id,不会按视频 ID 合并覆盖。
7. 详情工具
7.1 douyin_detail
功能
批量获取视频详情、真实播放链接、作者、互动、话题和时间信息。单次最多处理 8 个去重后的视频。
参数
| 参数 |
类型 |
必填 |
默认 |
说明 |
content_ids |
array/null
| 否 |
null |
旧模式视频 ID 列表;新流程不推荐 |
timeout |
number/null |
否 |
null |
单请求超时,null 时默认 60 秒 |
run_id |
string/null |
条件必填 |
null |
使用 candidate_ids 时必填 |
candidate_ids |
array/null
| 条件必填 |
null |
新模式候选 ID,必须属于同一 run_id |
组合规则:
- 有
candidate_ids 时忽略 content_ids,从数据库读取 aweme_id;
candidate_ids 模式缺少 run_id 返回 input_error=true;
- ID 不存在或不属于本次运行时整次输入失败;
- 去重后为空会报错;超过 8 条会报错;
- 新模式会追加保存每条成功或失败的原始证据,并重算对应候选门禁。
新模式返回结果
| 字段 |
类型 |
说明 |
title |
string |
成功数/请求数摘要 |
output |
string |
详情与失败项文本摘要 |
results_count |
integer |
请求视频数 |
success_count |
integer |
成功详情数 |
failed_count |
integer |
失败数 |
errors |
array
| content_id、error;错误文本最多保留 500 字符 |
duration_ms |
integer |
整批耗时 |
candidates |
array
| 刷新后的候选门禁摘要 |
candidates[].candidate_id |
integer |
候选 ID |
candidates[].aweme_id |
string |
视频 ID |
candidates[].gate_status |
string |
pending/pass/fail |
candidates[].failed_reason_codes |
array
| 未通过门禁原因 |
candidates[].evidence_version |
integer |
当前证据版本 |
旧模式额外返回
旧模式不自动关联候选,返回 details 数组;单条成功时额外返回 detail。每条详情常用字段包括:
content_id、channel_content_id、content_link;
title、body_text、content_type、topic_list;
video_url、video_duration、duration_seconds、cover_url;
channel_account_id、channel_account_name、channel_account_avatar;
play_count/view_count、like_count、comment_count、collect_count、share_count;
publish_at 及源数据中的创建、发布、修改时间;
image_url_list、video_url_list、multi_bitrate、bgm_data、is_original。
8. 画像与标准化工具
8.1 get_content_fans_portrait
获取单个视频的点赞用户画像。content_id 必须为 15~25 位纯数字 aweme_id。
8.2 get_account_fans_portrait
获取单个作者的粉丝画像。account_id 必须是完整 sec_uid,并以 MS4wLjABAAAA 开头。
8.3 两个单条画像工具的公共参数
| 参数 |
类型 |
必填 |
默认 |
说明 |
content_id / account_id |
string |
是 |
- |
内容或作者 ID |
need_province |
boolean |
否 |
false |
是否返回省份分布 |
need_city |
boolean |
否 |
false |
是否返回城市分布 |
need_city_level |
boolean |
否 |
false |
是否返回城市等级 |
need_gender |
boolean |
否 |
false |
是否返回性别分布 |
need_age |
boolean |
否 |
true |
是否返回年龄分布 |
need_phone_brand |
boolean |
否 |
false |
是否返回手机品牌 |
need_phone_price |
boolean |
否 |
false |
是否返回手机价格 |
timeout |
number/null |
否 |
null |
null 时默认 60 秒 |
8.4 两个单条画像工具的公共返回
| 字段 |
类型 |
说明 |
title |
string |
内容或账号画像标题 |
output |
string |
各画像维度的人类可读摘要;省份和城市只展示 TOP5 |
has_portrait |
boolean |
是否存在任一非空画像维度 |
portrait_data |
object |
画像维度对象;常见维度为年龄、性别、地域等 |
raw_data |
object |
上游原始完整响应 |
duration_ms |
integer |
调用耗时 |
单条工具不自动写入候选证据。需要持久化时应优先使用 batch_fetch_portraits 新模式。
8.5 batch_fetch_portraits
功能
按输入顺序逐条获取内容点赞画像;fetch_account_portrait=true 时同时获取作者粉丝画像,
否则仅在内容画像缺失且允许兜底时请求作者画像。单次最多 8 项。
参数
| 参数 |
类型 |
必填 |
默认 |
说明 |
candidates_json |
string |
否 |
"" |
旧模式 JSON 数组字符串 |
fetch_account_portrait |
boolean |
否 |
false |
是否始终同时取作者画像;老年受众判断建议为 true |
need_province |
boolean |
否 |
false |
同单条画像 |
need_city |
boolean |
否 |
false |
同单条画像 |
need_city_level |
boolean |
否 |
false |
同单条画像 |
need_gender |
boolean |
否 |
false |
同单条画像 |
need_age |
boolean |
否 |
true |
同单条画像 |
need_phone_brand |
boolean |
否 |
false |
同单条画像 |
need_phone_price |
boolean |
否 |
false |
同单条画像 |
timeout |
number/null |
否 |
null |
null 时默认 60 秒 |
run_id |
string/null |
条件必填 |
null |
使用 candidate_ids 时必填 |
candidate_ids |
array/null
| 条件必填 |
null |
新模式候选 ID,最多 8 条 |
旧模式 candidates_json 每项:
| 字段 |
类型 |
必填 |
默认 |
说明 |
aweme_id |
string |
是 |
- |
视频 ID;也兼容字段名 content_id |
author_sec_uid |
string |
否 |
- |
作者 ID;也兼容字段名 account_id |
try_account_fallback |
boolean |
否 |
true |
内容画像缺失时是否尝试作者画像 |
新模式返回
| 字段 |
类型 |
说明 |
title |
string |
批量完成标题 |
output |
string |
各候选画像获取摘要 |
count |
integer |
处理项数 |
duration_ms |
integer |
整批耗时 |
candidates |
array
| 刷新后的候选门禁摘要 |
candidates[].candidate_id |
integer |
候选 ID |
candidates[].aweme_id |
string |
视频 ID |
candidates[].gate_status |
string |
pending/pass/fail |
candidates[].failed_reason_codes |
array
| 门禁失败原因 |
candidates[].evidence_version |
integer |
证据版本 |
旧模式返回
旧模式返回 results,每项包含:
aweme_id、author_sec_uid、try_account_fallback、fetch_account_portrait;
content:ok/error/has_portrait/portrait_data/output;
account:attempted/error/skipped_reason/has_portrait/portrait_data/output;
age_normalization:两侧年龄标准化结果;
error:条目级错误。
批量画像允许逐项失败,不会因为一条上游失败而丢弃整批结果。
8.6 normalize_age_portraits
参数
| 参数 |
类型 |
必填 |
默认 |
说明 |
content_portrait |
object |
是 |
- |
视频 portrait_data 或其中的年龄字典 |
account_portrait |
object/null |
否 |
null |
作者 portrait_data 或其中的年龄字典 |
返回结果
| 字段 |
类型 |
说明 |
title |
string |
“年龄画像标准化” |
content |
object |
视频侧标准化结果 |
account |
object |
作者侧标准化结果 |
consistency |
string |
aligned/conflict/content_only/account_only/missing |
elder_score_cap |
number |
当前证据条件下建议的 E 分数上限 |
output |
string |
两侧强度、一致性与上限摘要 |
content、account 公共字段:
| 字段 |
类型 |
说明 |
has_age_portrait |
boolean |
是否识别到年龄维度 |
older_ratio |
number |
50+ 桶占比,范围 0~1 |
older_tgi |
number/null |
50+ 桶按占比加权 TGI |
mature_ratio |
number |
40~50 等成熟代理桶占比 |
strength |
string |
strong/moderate/weak/missing |
buckets |
array
| 原桶的 label/kind/ratio/tgi |
当前 elder_score_cap 规则:
| 证据情况 |
上限 |
| 内容与作者两侧都有画像 |
1.0 |
| 仅内容侧 |
1.0 |
| 仅作者侧且强证据 |
0.85 |
| 仅作者侧且非强证据 |
0.75 |
| 两侧均缺失 |
0.50 |
此上限是返回给模型的决策建议,候选更新工具不会硬校验 elder_score <= elder_score_cap。
9. 候选更新工具
9.1 batch_update_video_discovery_candidates
功能
严格按 candidate_id 批量更新候选详情、画像证据、R/E/S/V 评分、理由和分池。该工具只更新
候选,不新增候选、不修改搜索记录,也不结束运行。
顶层参数
| 参数 |
类型 |
必填 |
说明 |
run_id |
string |
是 |
运行 ID |
items |
array
| 是 |
非空候选更新数组 |
items[] 字段
| 字段 |
类型 |
必填 |
说明 |
candidate_id |
integer |
是 |
必须大于 0、存在且属于 run_id |
decision_bucket |
string |
是 |
仅 primary 或 rejected |
title |
string |
否 |
标题,最多 512 字符 |
content_link |
string |
否 |
内容链接,最多 1024 字符 |
author_name |
string |
否 |
作者名,最多 256 字符 |
author_sec_uid |
string |
否 |
作者 ID,最多 256 字符 |
tags |
array/string |
否 |
标签;与已有标签合并 |
publish_at |
string/number |
否 |
ISO 时间、日期或秒/毫秒时间戳 |
duration_seconds |
number |
否 |
秒;也兼容 video_duration |
play_count |
integer |
否 |
播放数,负值归零 |
like_count |
integer |
否 |
点赞数,负值归零 |
comment_count |
integer |
否 |
评论数,负值归零 |
collect_count |
integer |
否 |
收藏数,负值归零 |
share_count |
integer |
否 |
分享数,负值归零 |
content_age_evidence |
object |
否 |
视频侧原始/结构化年龄证据 |
account_age_evidence |
object |
否 |
作者侧原始/结构化年龄证据 |
age_normalization |
object |
否 |
标准化结果;兼容包在 result 等字段内 |
content_50_plus_ratio |
number |
否 |
视频侧 50+ 占比,必须在 0~1 |
content_50_plus_tgi |
number |
否 |
视频侧 50+ TGI |
account_50_plus_ratio |
number |
否 |
作者侧 50+ 占比,必须在 0~1 |
account_50_plus_tgi |
number |
否 |
作者侧 50+ TGI |
temporal_type |
string |
否 |
建议 evergreen/event/seasonal/festival/daypart |
temporal_status |
string |
否 |
显式 fail/unknown 会参与时间门禁;其他值由规则重算 |
temporal_evidence |
object |
否 |
时效判断证据 |
reject_reason_code |
string |
否 |
拒绝原因码,最多 64 字符 |
relevance_score |
number |
否 |
R,保存 6 位小数 |
elder_score |
number |
否 |
E,保存 6 位小数 |
share_score |
number |
否 |
S,保存 6 位小数 |
value_score |
number |
否 |
V,保存 2 位小数 |
decision_reason |
string |
否 |
最终判断理由 |
校验和重分类
- 任一
items[] 不是对象、缺少有效 candidate_id 或分池非法,整批在写库前失败;
- 不存在或不属于本次运行的
candidate_id 会使数据库更新失败;
content/account_50_plus_ratio 被硬校验为 0~1;
- R/E/S/V 当前只做数字转换和精度处理,不硬校验 0~1,也不自动计算
V;
- 请求
primary 但证据未齐时保存为 pending_evaluation;
- 请求
primary 但 P0 门禁失败时自动保存为 rejected;
- 请求
rejected 时即使门禁通过也仍保存为 rejected。
默认 P0 规则快照包含:时效有效、时长至少 30 秒、分享至少 1000、视频或作者任一侧 50+ 占比
至少 20%。部分缺失项可由代码中的高质量信号补偿;运行使用预创建时保存的规则快照,环境变量
可修改阈值。
返回结果
| 字段 |
类型 |
说明 |
title |
string |
“候选已更新” |
run_id |
string |
运行 ID |
updated_count |
integer |
成功更新候选数 |
reclassified_count |
integer |
门禁导致分池变化的数量 |
reclassified |
array
| candidate_id/requested_bucket/saved_bucket/failed_reason_codes |
candidates |
array
| 更新后候选摘要 |
candidates[].candidate_id |
integer |
候选 ID |
candidates[].aweme_id |
string |
视频 ID |
candidates[].decision_bucket |
string |
实际保存的分池 |
candidates[].gate_status |
string |
pending/pass/fail |
candidates[].failed_reason_codes |
array
| 门禁失败码 |
candidates[].pending_reason_codes |
array
| 尚缺证据的原因码 |
candidates[].evidence_version |
integer |
候选证据版本 |
candidates[].gate_evidence_version |
integer/null |
门禁使用的证据版本 |
candidates[].latest_gate_evaluation_id |
integer/null |
最近门禁评估记录 ID |
output |
string |
更新与重分类摘要 |
10. 运行控制与查询工具
10.1 update_video_discovery_run_status
参数
| 参数 |
类型 |
必填 |
默认 |
说明 |
run_id |
string |
是 |
- |
运行 ID |
status |
string |
是 |
- |
仅 running/finished/failed |
intent_summary |
string/null |
否 |
null |
Agent 对需求真实意图的总结 |
stop_reason |
string/null |
否 |
null |
停止搜索或失败原因 |
行为
finished:把所有剩余 pending_evaluation/unreviewed 候选归档为 rejected,刷新计数并计算业务结果;
failed:设置 outcome_status=failed;
running:只更新运行状态及可选说明,不清空既有搜索和候选。
业务结果:有效且按 aweme_id 去重的 primary 至少 5 条为 goal_met,1~4 条为 partial,
0 条为 no_match。
返回结果
| 字段 |
类型 |
说明 |
title |
string |
状态更新标题 |
run |
object |
完整运行摘要,见 10.3 |
output |
string |
run_id/status/primary_count 摘要 |
10.2 query_video_discovery_state
参数
| 参数 |
类型 |
必填 |
默认 |
说明 |
run_id |
string |
是 |
- |
运行 ID |
include_rejected |
boolean |
否 |
true |
是否包含 rejected;为 false 时仍包含 primary 和待评估候选 |
limit |
integer |
否 |
100 |
候选返回上限,代码约束为 1~500 |
返回结果
| 字段 |
类型 |
说明 |
title |
string |
查询标题 |
run |
object |
运行摘要 |
searches |
array
| 所有搜索页,结构见 10.4 |
candidates |
array
| 候选详情,结构见 10.5 |
output |
string |
搜索页数和主推荐数摘要 |
10.3 run 对象
| 字段 |
类型 |
说明 |
run_id |
string |
运行 ID |
biz_dt |
string/null |
业务日期 |
demand_grade_id |
integer/null |
需求分级记录 ID |
demand_word |
string |
需求词 |
seed_video_id |
string/null |
兼容旧流程的主参考视频 ID |
seed_video_title |
string/null |
兼容旧流程的主参考视频标题 |
intent_summary |
string/null |
意图总结 |
status |
string |
running/finished/failed |
search_count |
integer |
已保存搜索页数 |
primary_count |
integer |
当前 primary 记录数 |
valid_primary_count |
integer |
门禁通过且按视频去重后的 primary 数 |
outcome_status |
string/null |
goal_met/partial/no_match/failed |
attempt_count |
integer |
执行次数 |
stop_reason |
string/null |
停止或失败原因 |
rule_version |
string |
P0 规则版本 |
rule_config |
object |
本次运行冻结的门禁配置和评估时间 |
10.4 searches[] 对象
字段与 6.5 搜索页公共结构一致,但不含 run_id、candidates 和 persisted。查询态包含:
search_id、关键词与原因、来源和父子关系、供应商及分页状态、筛选参数、结果数、候选数、
has_more/next_cursor、执行状态、错误信息和原始证据 ID。
10.5 candidates[] 完整对象
| 字段组 |
字段 |
| 标识与来源 |
candidate_id、search_id、aweme_id、source_keywords、source_search_ids |
| 内容与作者 |
title、content_link、author_name、author_sec_uid、tags、publish_at、duration_seconds |
| 互动数据 |
play_count、like_count、comment_count、collect_count、share_count |
| 模型评分 |
relevance_score、elder_score、share_score、value_score、decision_reason |
| 分池 |
decision_bucket、reject_reason_code |
| 年龄证据 |
content_age_evidence、account_age_evidence、age_normalization、两侧 50_plus_ratio/tgi |
| 画像状态 |
content_portrait_status、account_portrait_status、portrait_conflict |
| 时效门禁 |
temporal_type、temporal_status、temporal_evidence |
| 门禁结果 |
gate_status、gate_results、rule_version |
| 证据引用 |
四类 latest_*_evidence_id、三类 *_fetch_status |
| 版本审计 |
evidence_version、gate_evidence_version、latest_gate_evaluation_id、gate_evaluated_at |
数据库旧值 unreviewed 在返回时统一映射为 pending_evaluation。
11. 内置工具 load_skill
参数
| 参数 |
类型 |
必填 |
说明 |
name |
string |
是 |
Skill 名称 |
返回
- 找到 Skill:返回包含 Skill 名称、说明和完整指令的上下文文本;
- 未找到:返回 JSON 字符串
{"error": "Skill '...' not found. Available: ..."}。
当前 find_agent 没有预加载 Skill,项目 skills/ 下也没有可发现的 SKILL.md,因此正常视频
发现流程不依赖此工具。
12. 非功能要求
12.1 性能与限流
- 内部关键词搜索:进程内相邻请求至少间隔约 10.1 秒;
- 作者作品:进程内相邻请求至少间隔约 10.1 秒;
- 视频详情:进程内逐条请求至少间隔约 10.1 秒;
- TikHub 搜索:进程内相邻请求至少间隔 1 秒;
- 批量搜索和批量画像均按顺序执行,不承诺并发;
- 单次 Agent 运行默认总超时 600 秒,工具自身默认上游超时通常为 60 秒。
12.2 可追溯性
- 每次搜索页都新增记录,不覆盖同参数历史页;
- 搜索、详情和批量画像新模式保存原始证据;
- 候选门禁记录证据版本和最近评估 ID;
- 运行完成后以数据库
outcome_status 和 valid_primary_count 为准,不能仅看最终文案。
12.3 数据安全与体积
- 单条画像工具返回
raw_data,可能体积较大;Agent 主流程应优先使用新模式批量画像的候选摘要;
- 搜索落库返回会移除原始响应和统一搜索结果大数组,但原始响应已保存到证据表;
- 错误文本可能包含上游响应内容,展示到前台前应做长度控制和敏感信息过滤。
13. 已知问题与产品改进项
| 优先级 |
问题 |
影响 |
建议 |
| P0 |
list[dict] 内部结构未进入 JSON Schema |
模型容易漏填 keyword/query_reason/candidate_id/decision_bucket |
使用 Pydantic 模型或 TypedDict 生成嵌套 Schema |
| P0 |
多数枚举和范围未进入 JSON Schema |
非法 source_type/status/sort_type 只能运行时发现 |
为参数增加 enum、minimum、maximum |
| P1 |
所有工具都返回字符串化 JSON |
调用方易发生二次解析遗漏 |
在框架层明确结构化工具结果协议 |
| P1 |
搜索工具的数据库 search_id 与 TikHub search_id 同名 |
翻页时容易传错 ID |
对外统一命名为 db_search_id/provider_search_id |
| P1 |
R/E/S/V 不做范围与公式校验 |
可保存越界分数或错误 V |
强制 0~1 并由代码计算 V |
| P1 |
elder_score_cap 只提示、不执行 |
模型可能给出高于证据上限的 E |
更新候选时加入硬校验或自动截断 |
| P1 |
单条画像工具不写证据 |
使用旧模式会出现结果存在但不可追溯 |
Prompt 和调用层只开放批量新模式,或给单条工具增加候选模式 |
| P2 |
批量搜索只返回部分 TikHub 分页字段 |
外部调用方难以手动接管中途分页 |
在 pages[] 明确返回 provider_search_id/backtrace |
| P2 |
错误结构不完全统一 |
调用方需兼容 error/errors/error_message |
定义统一 ok/code/error/data 包装 |
其中年龄上限应以本文件记录的当前代码值为准:仅作者强证据 0.85、仅作者非强证据 0.75、
两侧缺失 0.50。旧文档中的 0.65/0.35 已不符合当前实现。
14. 验收标准
14.1 文档验收
- 工具数量与
create_find_agent().tools.list_tools() 一致;
- 每个工具的顶层必填项、类型和默认值与运行时 Schema 一致;
- 搜索任务、候选更新项等嵌套字段与运行时代码校验一致;
- 返回字段可在对应实现或 Service 序列化函数中逐项定位;
- 明确区分数据库 ID、平台 ID 和供应商分页 ID。
14.2 调用验收
- 搜索成功后必须得到
search_id 和至少零个 candidate_id,且 persisted=true;
- 详情/画像新模式必须使用同一
run_id 下的 candidate_ids;
- 候选更新后必须读取实际
decision_bucket 和 gate_status,不能假设请求分池等于保存分池;
- 结束前必须调用状态查询核对搜索数、候选分池和门禁;
- 正常业务结束必须调用
status=finished,并以返回的 outcome_status 为最终结果;
- 任一返回含
error 时都必须显式处理,不得视为成功继续。
15. 代码依据
| 范围 |
代码位置 |
| Agent 注册工具 |
agents/find_agent/tools/__init__.py |
| 运行时 Tool Schema |
supply_agent/tools/base.py |
内置 load_skill |
supply_agent/agent/core.py |
| 搜索工具 |
agents/find_agent/tools/ 与 agents/find_agent/support/douyin_*.py |
| 搜索持久化 |
agents/find_agent/support/search_persistence.py |
| 详情与画像 |
agents/find_agent/support/douyin_detail.py、portrait.py、age_portrait.py |
| 候选与运行工具 |
agents/find_agent/support/video_discovery.py |
| 返回对象序列化 |
supply_infra/services/video_discovery_service.py |
| P0 门禁 |
supply_infra/video_discovery_gates.py |