Agent Engineering 课程阅读

在 GitHub 查看原文

本页目录

L01 练习

code.pyresearch_assistant/schedules.py,运行观察变化。零外部依赖、零等待。


练习 1:把漂移语义的月度账算出来(理解类)

code.py Part 1 里 daemon 每天晚 6 小时 tick。

  1. 改成「每天晚 2 小时」,跑 30 天(循环里 advance 改一下),记录漂移语义下第 30 班的班点。
  2. 回答:如果盯梢任务的价值依赖「在竞品发日报之前扫到」(比如每天 8 点前),漂移语义几天后开始失约?

验收:给出第 30 班的漂移量,和「开始失约」的天数。


练习 2:设计实验——mark_fired 和 dispatch 的顺序(设计实验类)

Scheduler.tick()mark_fired 先于 dispatch(至多一次语义)。

  1. 假设:交换顺序(先 dispatch 后 mark_fired)会变成至少一次语义——dispatch 成功但进程在 mark_fired 前崩溃,重启后同一班会被再次触发。
  2. 实验设计: - 写一个 dispatch 抛异常的场景(测试 test_dispatch_exception_does_not_lose_fire_record 已有),确认当前语义下该班不会重复触发。 - 复制 Scheduler.tick() 改成先 dispatch 后记账的 tick_at_least_once(),同场景下再跑:dispatch 抛错后再 tick 一次,观察同一班被触发两次。
  3. 思考:至多一次丢的是什么(这班的任务没登记成)?至少一次丢的是什么(重复登记)?哪种丢法能靠已有资产兜住?(提示:重复登记 job → 跑两次研究 → 若有副作用靠 L04 幂等键挡;任务没登记成 → 这班永远缺了。盯梢任务哪种更可接受?)
  4. 预期:两种语义都跑通后你会发现:盯梢任务选至多一次 + 下一班反正会再扫,比至少一次 + 幂等兜底更简单——因为盯梢的每一班本来就是「重扫世界」,漏一班的损失下一班自动补。

验收:说清两种语义各丢什么、为什么盯梢场景选至多一次。


练习 3:设计实验——首班「注册即到期」还是「等一个周期」(取舍类)

add_schedule 缺省 first_run_at=now(注册即到期,下一次 tick 立即建仓)。

  1. 假设:改成 first_run_at=now+interval(等满一个周期才首跑),盯梢任务的体验会变差——注册后 24 小时内你对这个主题一无所知。
  2. 实验设计:改 code.py Part 2 的注册参数,观察 Day1 是否还触发。
  3. 思考:什么场景该等满一个周期?(提示:任务本身有副作用、或首跑成本极高需要错峰——「注册即跑」对报表类任务可能撞正忙时。)

验收:两种缺省各举一个适用场景。


练习 4:思考题——为什么 no_change_streak 现在就建在表里(前瞻类)

schedules 表里有一列 no_change_streak,本课恒为 0,注释写着「L07 自适应扫描用」。

  1. 思考:调度器(L01)和变化检测(L02)是两个模块,为什么「连续几天没变化」这个信息最终要落回调度表?(提示:它影响的是「下一班隔多久」——这是调度器的职权;watcher 只负责报告「这次有没有变化」。)
  2. 思考:如果把退避逻辑放进 watcher(发现没变化就自己 sleep 更久),会破坏哪条本课立的规矩?(提示:职责边界——watcher 管感知,调度器管班次;以及 sleep 进业务模块 = 不可快进测试。)

验收:一句话说清「退避是调度职权」的理由。