birdwatch
来自开放网络的研究,由一个代理驱动,每个命令一步。代理计划,分类,
检查和停止;观鸟者搜索,打开页面,在报价门后提取发现,检查
他们,并把每一个记录在一个分类账上。每一个发现都是一个句子,在页面上引用
运行阅读。 skills/birdwatch/SKILL.md (在这个回购中)是代理如何驱动它。
阅读网页和文件(获取阶梯,HTML和PDF文本,视频)是
@wrenautomation/read每个模特的电话都接通了
@wrenautomation/models。在0.29.0之前,有三个软件包:raven(一个模型规划器,在0.30.0时消失了)
代理计划)、猎鹰(./document)和weaver(引擎、源、分类账和CLI)。
| 进口 | 做 |
|---|---|
@wrenautomation/birdwatch/engine | Source (一个名字, search 和/或 open(成本); registry 计划的允许清单;座席的呼叫(planRound, search, open, extract, check, add, accept, brief),每人一步;法官的通行证(judgeHits, judgeDocuments, judgeFindings, judgeStats); fold 从运行的记录中重建运行的状态,因此再次步进运行会跳过已完成的操作; Transient失败值得再试一次;ask和plan文件形状(Ask, PlanFile, Query, QueryTree, Edge, Snapshot),以及每一品种的股票计划档案(web, video, channel, person, site来源,预算, age, rules,查询树指南) |
@wrenautomation/birdwatch/sources | searxng, exa (搜索), youtube (搜索和读取,yt-dlp), fetcher (开门,礼貌的取货者) ladder (打开autobrowse的取回阶梯到浏览器), reddit 和 facebook (通过autobrowse的站点路由打开一个线程或群组帖子), google (b谷歌通过桌面浏览器自己的页面:每个结果一个点击,AI概述一个点击,其文本作为片段,每个页面引用一个点击), arxiv (搜索和读取:里面的API BIRDWATCH_ARXIV_CATEGORIES,每次点击都以OpenAlex的引用次数和评论为主导;全文从HTML中读取,否则从PDF中读取;每3秒呼叫一次; paste (一个人的网址), ledger (命中较早的运行看到)。的查询 site 跳过无法保持它的搜索器(Source.keeps: youtube 只在YouTube上播放)。A跟随(Source.follows, follow)列出页面作者的帖子(youtube:一个频道的上传,从视频或频道,以及TikTok的个人资料; reddit:用户最热门的帖子和评论)或类似的页面(exa: findSimilar) |
@wrenautomation/birdwatch/ledger | 记录(query, hit, document, finding, verdict, call, spend, snapshot, edge, done, steer, gap, check, pattern, found, judge, person), FilesLedger (一个文件夹: runs/<run>/<writer>.jsonl, plans/<kind>.json), MemoryLedger,每个来源、每个人、每个渠道和每个种类的产量行 |
@wrenautomation/birdwatch/document | 文件方面: Document, Finding, Proof, Verdict (zod)、媒体读者(html, pdf, text), claimExtractor (引用文档的发现,通过gate,以及对文档的判断:其质量和请求的差距;对发现或它们的长度没有上限,并且模型的输出上限从最后保存的引用继续) Model 接缝,它需要和 Cut 当一个模特的帽子剪断一个答案时,他就扔了 |
每条记录都承载着 from (人工智能,人或工具)和 by (代理或模型id、来源
人)。一个人的保留或删除记录与代理人的记录相同。计划文件归档
plans/<kind>.json 在分类帐(来源、预算、年龄、规则、树指南)旁边是一个运行的地方
学习: birdwatch learn <kind> 从跑步中学到的东西中写出下一个版本
协议;没有调优文件的类型运行库存文件(birdwatch plans <kind> 打印)。
brief.guide 向代理人显示种类的年龄判决和规则。
命令行界面
需要节点24+。 read 和 watch 需要yt-dlp和ffmpeg。
npm i @wrenautomation/birdwatch
npx birdwatch fetch https://example.com/report --contact [email protected] # a page as text
GEMINI_API_KEY=... npx birdwatch read https://www.youtube.com/watch?v=... # captions + screen
COHERE_API_KEY=... npx birdwatch read https://www.instagram.com/reel/... # watched: speech, screen, cuts
npx birdwatch list 'ytsearch10:cold email' --to 10 # hits as JSON, no downloads
npx birdwatch text report.pdf # a file on disk as text
npx birdwatch page saved.html --url https://example.com/report # title, text, links as JSON
COHERE_API_KEY=... npx birdwatch watch talk.mp4 # speech, on-screen text, cuts
npx birdwatch plans web > ledger/plans/web.json # a stock plan file, to tune
一个代理(Claude Code,或任何带有shell的代理)每次只执行一个命令来驱动引擎:it 在它自己的头脑中计划,分类,审查和停止,引擎做固定的工作(搜索, 打开,提取报价门后,检查)并保存记录。每个命令打印JSON。
export BIRDWATCH_AGENT=claude-code # the agent's id on every record it writes
birdwatch plan "how do staffing firms win repeat clients" --known "referrals convert" # a run; prints its id
birdwatch plan "who buys growth help" --premise "coaches are the buyer" # a premise gets a tree facet that tests it
birdwatch brief 01M5YS... # the ask, budget, sources, what is open, hits, findings, cost
birdwatch recall staffing repeat clients --not 01M5YS... # earlier runs' findings: quote, URL, source date, run; --also <ledger> per extra folder
birdwatch search 01M5YS... "staffing repeat client rate" --why "the ask's words" # one query, then every searcher
echo '[{"terms":"...","why":"..."},{"terms":"...","why":"..."}]' | birdwatch search 01M5YS... # a batch
birdwatch search 01M5YS... < tree.json # a query tree, one tier: {facets: [{name, why, tries: [[{terms, why}], [...]]}]}
birdwatch search 01M5YS... < tree.json # after triage, the same file: the next try of each facet still thin in kept hits
birdwatch add call 01M5YS... 01M5YT... keep --why "a survey with numbers" # triage: a hit kept
birdwatch add call 01M5YS... 01M5YU... drop --why "a vendor page"
birdwatch open 01M5YS... 01M5YT... --url https://a.example/report --why "numbers" # keep these, read every kept hit
birdwatch open 01M5YS... --with ladder # an opener the run lacks joins it, to open only
birdwatch show 01M5YS... 01M5YV... # a document's text, for the agent to read itself
birdwatch add finding 01M5YS... 01M5YV... --text "412 firms were surveyed." --quote "A 2025 survey of 412 firms"
birdwatch add check 01M5YS... 01M5YW... --ok --why "the quote says it" # the agent's own check; --fail also drops
birdwatch extract 01M5YS... # or a model behind the quote gate, every document without a verdict
birdwatch check 01M5YS... -n 3 # or a model's sample of findings read against their documents
birdwatch check 01M5YS... --patterns # every unchecked finding a pattern rests on
birdwatch accept 01M5YS... keep --over 0.8 --why "serves the ask" # the judge's hints in bulk, at the agent's bar
birdwatch accept 01M5YS... class --min 0.8 --why "head of page" # also: drop --under 0.2
birdwatch add gap 01M5YS... "no UK numbers yet"
birdwatch add steer 01M5YS... "numbers only" --human will # the person's word, relayed
birdwatch add pattern 01M5YS... "Repeat clients come from referrals." --on 01M5YV... 01M5YW... # what findings say together; sites counted
birdwatch add edge 01M5YS... again --why "thin on the UK" # the review: a new round
birdwatch plan --run 01M5YS... # round 2: known, steer and what round 1 left open, in its snapshot
birdwatch plan "coaches: who pays for setters" --parent 01M5YS... --why "the best niche of round 1" # a child run
birdwatch add dead 01M5YT... spend --why "found consumers, not buyers" # later tries skip the facet
birdwatch follow 01M5YS... --from 01M5YV... --as posts --why "the speaker's other talks" # the author's own posts; --as similar: pages like it; a paper: --as refs (what it cites) or citers (what cites it)
birdwatch add person 01M5YS... "Bee Speaker" --profile https://www.youtube.com/@bee --aka Bee --why "one speaker" # one person across sites
birdwatch learn web --sources searxng exa --rounds 4 # the plan file's next version, after a good run
birdwatch learn web --thin 2 # the tree's guide: a try under 2 new hits falls through
birdwatch learn web --show # the current one
birdwatch add edge 01M5YS... stop --why "enough"
plan 打开一轮:它的快照包含了问题,已知的(到目前为止的发现),每一个
舵手,上一轮还有什么空缺,允许名单和预算。没有疑问,代理人来了
通过 search 或者 add query,从不封顶。预算是一道护栏: brief 显示它,并且
一条边 again 过去的 budget.rounds 打印的是警告,而不是拒绝。 search, open,
extract 和 check 每个程序运行一个步骤并打印它所写的内容(文档的文本) chars);
一个带着音符放弃出口的步骤。 open 读取每一个保存命中的运行,没有
文档; extract 每一份没有判决的文件; check 的跨文档示例
保留尚未检查的发现。 add 手动写入一条记录:查询,查找(引用)
必须逐字逐句地在文档上,否则添加失败,并带有门的“为什么”,检查(?
代理人自己对与其文件不符的调查结果的解读;失败也会丢弃它),调用(keep或
投掷命中或发现),边缘(again, stop, back --to <step>)、缺口或转向(总是如此)
人的: --human [name]). 每一个 add 需要 --why 当决策需要时。一个
--human 记录是当事人通过代理人的话: from: human, by 他们的名字。
当智能体给出一个面(研究者覆盖的边)时,一轮搜索是一个树
数字,如何,谁,相反的观点,主要来源;计划文件的 tree 指南给它们命名),
每个都按顺序尝试,每个都尝试一个查询列表。 search 每次呼叫运行一个层
Fetch:第一次调用,每个facet的第一次尝试;每次调用后,每个方面的下一次尝试
比向导留下的子弹少 thin (默认为3)。的一个侧面 thin 完成;一个方面
没有名字的呼叫等待分类;有一个面没有了,仍然很薄,这是一个缺口,
写一次。尝试失败的结果是分诊保留了什么,而不是搜索者保留了什么
返回:每个搜索者返回一个页面。 --all 负责所有方面的下一步尝试
保存。第二次查询返回的页面是 found 第一炮就录,第二炮就不录了
命中,每一击都被视为命中。 brief.hits.uncalled 列出每个
首先,用找到它的面来击打; brief.tree 用它写的东西显示每一次尝试,
kept 和 uncalled 每一个方面。没有查询服务的向导facet在注释中被命名。
learn --thin <n> 或者 --tree <file> 调整指南。
代理自己读取: show <run> <document> 打印文档中存储的文本, add finding 在同一扇门后面写着它读到的东西, add check 它自己的支票。 extract 和
check 在同一扇门后面放一个模型,以增加体积;两个路径都写相同的记录。
代理人:通过代理人或亲自:
npx birdwatch add steer 01M5YS... "numbers only; skip vendor pages" --human # what you say: the brief shows it first
npx birdwatch add gap 01M5YS... "no UK numbers yet" --human # what the run lacks: the next plan reads it
npx birdwatch add edge 01M5YS... back --to fetch --why "searxng was down" --human # the step to run again
npx birdwatch trace 01M5YS... --type finding spend # the run's records, JSON lines
npx birdwatch add call 01M5YS... 01M5YT... drop --why "a forecast, not a result" --human # a call in your name
npx birdwatch yield --source exa # hits, reads, proposed, kept
npx birdwatch sources # what this machine can run
npx birdwatch serve --port 4747 # the ledger over HTTP for a viewer, read only
模型是 anthropic 默认(Claude Haiku直接, ANTHROPIC_API_KEY; --model anthropic:sonnet|opus|id 另一个) --model gateway[:alias] Wren的LLM入门课程
(WREN_LLM_GATEWAY_URL, WREN_LLM_GATEWAY_TOKEN),或者在stdin上读取提示符的任何命令
并打印出答案(claude -p --output-format json 是克劳德代码无头)。模型确实如此
仅散装(提取,检查);代理决定。源来
来自环境: SEARXNG_URL (和 SEARXNG_TOKEN举个例子,在a后面
代理), EXA_API_KEY (或 _1..n), GEMINI_API_KEY 对于没有字幕的视频,
BIRDWATCH_CONTACT 对于取回器和 arxiv (无联系人,无页面打开; OPENALEX_API_KEY免费的;给予的 arxiv 它自己的引用预算,和 SEMANTIC_SCHOLAR_API_KEY,免费,按自己的价格收费 --as refs; --sources arxiv 命名它(因为没有股票计划文件这样做),也为梯子命名
AUTOBROWSE_URL 和 AUTOBROWSE_TOKEN (一个worker的HTTP面)或 RESTATE_INGRESS_URL 和
RESTATE_AUTH_TOKEN (Restate入口,后面坐着一名办公人员; POST /desk/call;
AUTOBROWSE_SERVICE 获取另一个服务名称)。同一个工人给了 reddit 和
facebook 读者。 BIRDWATCH_ACCOUNTS 指定每个站点读者可以登录的帐户
(reddit=reddit@alt); 没有条目的站点只能读为已注销。分类帐文件夹为 --ledger 或者
BIRDWATCH_LEDGER (默认 ./ledger); --writer 或者 BIRDWATCH_WRITER 在其中命名您的文件。
法官是 --judge 或者 BIRDWATCH_JUDGE (jev, jev:<model>, fake, off); 没有,
jev 当 TYPESAFE_API_KEY 是,否则为空。 --no-judge 为一个命令关闭它。
每个开放源代码都声明它打开的url (opens): youtube 一个YouTube页面, fetcher 和
ladder 任何其他http(s)页面 reddit Reddit帖子或评论永久链接, facebook 一个
公共群组帖子。网站自己的阅读器(first在开幕式前轮到它了。
无论允许列表的顺序如何:它都将线程作为数据响应,其中获取的页面是一个墙。
reddit 阅读先签出(reddit-public线程的馈入);只有当那错过和
BIRDWATCH_ACCOUNTS 命名一个帐户,它是否要求再次登录。 facebook 总是
签署。用过的帽子或拒绝阅读的信都是错过;忙配置文件(503)或无应答重试。
拒绝在其原因中携带工人的访问码: need_login, platform_blocked,
rate_limited 或者 upstream_broken。最后两个从未读过登录:这两个都不能解决。
读取步骤要求在调用之前,所以一个源永远不会
打开一个hit就等于不花钱。获取的页面没有任何可用的内容(403,块)
梯子的最后一个梯级还在响,一个没有读者的媒体,一个梯子的答案不是HTML这样的
作为PDF)是一个失误:源抛出,它的 spend 说 ok: false 有了理由,下一个
揭幕战轮到你了,每场揭幕战没打到的命中都是 gap 上面列出了每个原因。一个页面
它的答案是200,但仍然没有任何内容(一个captcha墙,一个“未找到”的shell,低于200)
文字)同样是错过,以标题或计数为原因。运行的
快照将其源固定在 plan: sources,允许列表,搜索,打开和跟踪;
opens,注册表的其他打开器(除非 --sources 是给定的),哪个打开和跟随但是
从来没有搜索。 open --with <source> 写入一个新快照,该快照将一个添加到 opens (读
注:当命中未命中时,会命名它们)。这个
梯子花费了浏览时间和工人每天的工作时间 fetch 每个调用的桶。穰的搜索
要求每个结果有一个亮点(三个句子,每个结果计费)作为命中的 snippet.
每个模型调用都是一个 spend 记录模型id,输入和输出令牌,以及 usd 从
标价(src/app/prices.ts:克劳德的俳句、十四行诗和作品5.5;网关的 free
别名为$0;另一种模式保留代币,没有价格)。 run 在stderr上打印运行总数
和作为 cost 在JSON中,最后一次复习的边缘(edge(下一个和为什么)同样的方式;
brief 将总数打印为 cost.
run 当运行在一个放弃的步骤上停止时退出2(没有模型,没有源,一个块):
--resume 一旦问题解决了就继续。失败值得再试一次(A 429, A 5xx, A
断开连接)尝试三次并暂停,每次尝试a spend 记录;一个步骤
仍然不能继续写不 done, run 等待并重新开始,最多五次,
在它退出之前。搜索、读取和摘录呈扇形分布(一次读取或摘录四次);
每个文档的记录在其批处理结束时着陆,并且再次执行步骤会跳过其记录
显示完成。永远失败的提取(模型的答案无法解析,为400)将停止
根据目前记录的调查结果和出口2: extract 再次只要求
没有判决的文件。削减产出上限的一个模型答案不是失败,而是整体失败
发现之前的削减通过闸门和模型再次要求其余的
已知这些发现的文件(./document的 Cut;这个 spend 携带两个调用(令牌)。
轮盘之间,这个人看书 brief (或代理人告诉他们),保留或丢弃发现(add call),并以自由文本(add steer). 每一个 steer 记录显示首先在
简短的,在它之后的回合的摘录提示。 budget.rounds 是一名警卫
铁轨,不是停止规则:通过它,边缘的原因说明了为什么再打一回合是值得的。
这些步骤用英语记录。每个搜索者都回答了这个问题,没有新的命中,并且保留了一个
打无源打不开(一个403,一个挡梯子打不开),各写一个 gap; 那么
add gap。一轮的回顾读的是差距和一个人的去留与其原因;接下来的
Round的计划会读取它们,而评论就是为什么 again,在“最后一轮未结束”下。
add edge back --to <step> 写一个人的边缘:折叠把它当作代理人。一个 pattern
(add pattern用代理人的话说,是几份保存下来的调查结果的总和;它的计数
不同的地点是从发现的证据中计算出来的,从未声称过,并且 brief.patterns 列表
他们的报告。跑步可以是一个孩子(--parent <run> --why):它的快照命名父快照,它的计划读
父母和兄弟姐妹发现了什么(回想那些运行),它的预算是父母的
最多。计划文件的 runs.depth (2)是护栏:更深的孩子警告。两个封盖停止
每轮家长的子女数(runs.children, 6),整棵树的读数为(runs.reads,固定
在根目录的快照上 treeReads; 默认情况下,根节点的读数为x,四舍五入x(子节点+ 1)。
open 在树冠处停止或切断它的攻击; brief.lineage 和 brief.treeRoom 显示了
先人又离开了房间。一个
停止儿童的停止,模式和死角(add dead)达到父母的下一个计划
已知线;一个奔跑的孩子是开放的。一个 class (add class)表示文件的来源类型(原始数据、调查、
从业者,供应商,论坛,新闻,其他),以及为什么;它的研究结果证明了这一点,而且是一门课
发现超越了它。 brief.patterns[].classes 计算每个类的来源:不同的站点,
但每个论坛线程都有自己的; echo 标记一个分类源都是供应商的模式,
和 unchecked 列出未检查到的结果。只有代理人或一个人写
类。一个树面 needs 命名可以证明这一点的类; tree.facets[].lacks 说
它的读页没有(而facet没有) enough),以及其每次尝试都标记一个站点的facet。一个 draft (add draft(JSON项在stdin上)是一个粗略的草案
发现和模式:该研究的草稿门中有一个项目没有提及任何保留或有数字
没有引用过。 brief.draft 显示最新的。这永远不是最后的决定。
检查步骤读取本轮保存结果的样本(budget.checks,默认为3,或a
保存结果的十分之一,以较多者为准;0为无;分散在文件中);
check --patterns 阅读每一个未检查的找到一个模式依赖,针对文本周围的每一个引用。提取门证明引用是
在纸上;检查询问它是否支持句子。失败的发现得到A check
记录和挂断电话; add call <finding> keep 把它放回去。一次失败伴随着一次补救
适合:一个较窄的句子,同样的引用。修复通过提取门和第二个
检查,然后作为新发现登陆 fixes 给旧的命名。审查看到每一个检查和发现
携带其文档的日期,因此评审将时间视为计划文件的时间 age 行说。
法官(杰夫,来自 @wrenautomation/models/judge)用概率回答输入的问题
也没有短信,所以它不会写电话或支票。 search 对每一个新的热门作品都要求它,然后去做
为客户服务,谁写的(客户,或者卖家),什么
类。 open 向每个新页面询问它的类。 check 问每个不停找的人一句:做什么
引用它,它是否归功于另一个来源。每个答案都是一个 judge 记录每一次通话
消费。他们暗示和路线: brief.hits.uncalled 按面排序然后法官判罚,然后
显示答案; documents.unclassed[].guess 显示它的等级;的一面 needs 不是
只要它的保留命中有等级(经纪人的,否则法官的),就足够了,不需要;
patterns[].cites 列出信任其他来源的发现,供应商重复警告名称
他们。 check 阅读样本,再加上每一个法官支持的结果都在0.8以下:法官的回答是“不”
取出一个。 accept 在特工自己的酒吧里把提示变成记录,每个都有
法官的号码在它的为什么。 brief.judge 计算其呼叫,成本,以及代理和客户的频率
我同意。试验(0.22.0): open 还要求每个页面的 worth (你会小心吗?
研究人员引用它的问题)。 documents.toExtract[].worth 显示了它; brief.judge.worth
给出了它的AUC,以防止“对它的发现被保留”,以及半门会跳过什么。没有什么
盖茨还在研究。
从0.25.0开始,法官通读整页:正文到参考文献(附录保留)
每个部分有64000个字符,最多4个,每个部分回答最多的是“是”。杰夫的意见是
便宜(每百万代币约0.04美元),所以一张纸的成本约为十分之一美分
标准(--criterion name="question",在 plan)是一个人自己的是或否测试
好的来源:法官在每一页每一击中都问了每一个人,并且简报显示了它的几率
在每次击球(发球和测试)中作为提示。他们卑劣的种类 hits.uncalled 和 documents.toExtract; brief.judge.criteria 给出了每个人的AUC
“关于它的发现被保留了下来”,在点击和页面上。只是一种暗示,而不是一扇门。
从0.27.0开始,提取器也读取主体(引用列表中没有发现)。每一个评论
查看之前每一轮的新发现和保留的发现,并决定何时停止。一篇论文的
follow --as refs 和 --as citers 列出它引用了什么和引用了什么。一次检查(25篇论文,参考十四行诗):
在整个页面上,Jev的标准赔率将十四行诗的“是”与“否”进行排序,AUC为0.94比1.00;在
摘要:0.77 ~ 1.00。
的查询记录 follow: {url, as, document?} 和术语 <as> of <url>。这个
Fetch步骤将其发送到源 follows 需要它, follow 列出多达30个,以及
点击经过分类,读取和大写就像搜索一样。每个查询都进入allow列表
就像它写的时候一样:一个来源 follow --with 允许加入连接 opens,所以它运行
跟随,从不搜索。一个
person 在网站上命名一个作者(个人资料url,他们在下面发布的名字);文件是
当一个帖子从他们的个人资料中找到它时,当它的URL位于个人资料下时,或者
当它的频道(或它的热门频道)是它们的名字之一时。 brief.people 计算每个人的
文件、保存的调查结果和地点; brief.unfollowed 列表保存了没有后续内容的页面
没有人拥有。
serve 将分类帐放在127.0.0.1以供查看者(Wren门户的Research页面)。只读:
CLI仍然是唯一的写入器。 GET /runs 每次运行给出一行(ask, parent, round, next step,
计数、花)。 GET /runs/:run 给出了一个 RunView (v: 1):简短,每个查询都有命中
它写了又找,每一击都有它的来源,查询,呼叫和判断,每一页都有它的
阶级,判决和个人,每一个发现及其检查,决定和步骤的时间表结束
每个来源都有自己的理由和花费。 GET /runs/:run/documents/:doc 给出页面存储的文本。
GET /events 发送 event: run 与 {run} 每次运行文件更改时,每25秒ping一次;
然后,观众会再次看到这段视频。歌珥的答案 --origin (默认情况下是门户)和任何
localhost,并对Chrome的私有网络预飞行表示同意。这些类型生活在
src/engine/view.ts; 主机复制它们并进行检查 v美国从不进口。
图书馆
import { PoliteFetcher, userAgent } from "@wrenautomation/read/fetch";
import { readPage } from "@wrenautomation/read/text";
const fetcher = new PoliteFetcher(userAgent("[email protected]"));
const res = await fetcher.get(url);
const page = readPage(res.text, res.url);
引擎,有你自己的模型和源:
import { claimExtractor } from "@wrenautomation/birdwatch/document";
import { extract, open, planRound, registry, search } from "@wrenautomation/birdwatch/engine";
import { FilesLedger, ulids } from "@wrenautomation/birdwatch/ledger";
import { exa, fetcherSource } from "@wrenautomation/birdwatch/sources";
const ledger = new FilesLedger("./ledger", "will");
const sources = registry(exa({ keys }), fetcherSource({ fetcher }));
const deps = { sources, ledger, model, extractor: claimExtractor, clock: () => new Date(), ids: ulids(), writer: "will" };
const agent = { from: "ai" as const, by: "my-agent" };
const { run } = await planRound(deps, { ask: { text: "how do staffing firms win repeat clients", kind: "web" }, planFile, model: model.id });
await search(deps, run, [{ terms: "staffing repeat client rate", why: "the ask's words" }], agent);
await open(deps, run, { urls: ["https://a.example/report"], why: "a survey" }, agent);
await extract(deps, run); // findings, each with its proof: a quote on a page the run read
具有自己的分类帐、源或模型挂载的主机
相同的命令: addEngineCommands(program, { ledger, sources, model, extractor }) 从
@wrenautomation/birdwatch (雷恩 research 命令是这些在Postgres上)。
开发
pnpm install
pnpm lint && pnpm typecheck && pnpm test
一、 v* 标签向NPM发布(.github/workflows/release.yml可信发布:不存储令牌)。
许可证:PolyForm Strict 1.0.0 (LICENSE.md)。