Future AWS Agent Engineer? I Didn't Write the Code. Does It Count?

Future AWS Agent Engineer? I Didn’t Write the Code. Does It Count?

未来的 AWS 智能体工程师?我没写代码,这算数吗?

A few weeks ago I wrote about hitting ReAct in the coursework and having a record scratch moment, because I had already met it without knowing its name. That post ended on a section called “Building Ahead of Understanding,” which was me making peace with shipping things before I fully understand them. 几周前,我写到在课程中接触到 ReAct 时那种“唱片跳针”般的错愕感,因为我其实早就用过它,只是不知道它的名字。那篇文章结尾处有一个章节叫“在理解之前构建”,那是我在与“在完全理解之前就交付成果”这种状态达成和解。

This week I shipped my first chatbot. It passed on the first attempt, on deadline day, on a project where the rubric was grading a product AWS had already discontinued. And I spent most of that day quietly worried that it did not count. 本周,我交付了我的第一个聊天机器人。它在截止日期当天一次性通过了测试,尽管该项目的评分标准针对的是 AWS 已经停用的产品。那天大部分时间里,我都在暗自担心:这到底算不算数?

Let me be clear about what the worry actually was, because it was not about cheating. Using AI agents to build a coding project is allowed here. I asked before I started, I got a yes, and I disclosed the whole arrangement in my README, including a section that names what each tool did and what I did. Nobody was misled about how this got built. 我得澄清一下这种担忧的本质,因为它与作弊无关。在这里,使用 AI 智能体来完成编程项目是被允许的。我在开始前询问过并得到了许可,且在 README 中披露了整个协作安排,包括专门列出每个工具做了什么、我做了什么。没有人被误导。

The worry was smaller and more personal than that. I still did not type the code. My agents did. I directed, I validated, I decided, and underneath all of it was a small voice asking whether directing is the same as knowing. Whether a person who cannot write a Bedrock call from memory gets to say they learned Bedrock. Here is what I found out. 这种担忧更细微、更私人。我确实没有亲手敲代码,是我的智能体写的。我负责指挥、验证和决策,但在这一切之下,有一个微弱的声音在问:指挥是否等同于掌握?一个无法凭记忆写出 Bedrock 调用的人,是否有资格说自己学会了 Bedrock?以下是我发现的答案。

The starter files were a generation behind the instructions. The project is a customer support chatbot on the Amazon Bedrock AgentCore managed harness. Three routes, one system prompt. A bug report gets collected across turns and filed to DynamoDB through a gateway tool. A platform question gets answered from an embedded FAQ. Everything else gets a polite redirect to a human. 初始文件比说明文档落后了一个版本。该项目是一个基于 Amazon Bedrock AgentCore 托管框架的客户支持聊天机器人。它包含三条路由和一个系统提示词。错误报告会在多轮对话中收集,并通过网关工具存入 DynamoDB。平台相关问题则通过嵌入的常见问题解答(FAQ)来回答。其他所有问题都会被礼貌地转接给人工。

I named it Nova Trivium. A trivium is the place where three roads meet, which is the whole architecture in one word. Then I opened the starter files and nothing matched the instructions. The eval script called invoke_flow on a Bedrock Flows client. The Lambda rejected every request that did not carry a messageVersion envelope, which is the Agents Classic shape, and Bedrock Agents Classic closed to new customers on July 30, 2026. 我给它起名叫 Nova Trivium。“Trivium”意为三条道路交汇之处,这一个词就概括了整个架构。然而,当我打开初始文件时,发现一切都与说明文档对不上。评估脚本调用了 Bedrock Flows 客户端的 invoke_flow,而 Lambda 拒绝了所有不带 messageVersion 信封的请求——那是旧版 Agents Classic 的格式,而 Bedrock Agents Classic 已于 2026 年 7 月 30 日停止向新用户开放。

The CloudFormation template created none of the IAM roles the instructions promised. And requirements.txt pinned boto3 to 1.42.54, when the AgentCore APIs need 1.43 or newer. That last one was the tell. A version pin below the floor of the API you are supposed to call means the bundle predates the thing it claims to build. The instruction pages had been rewritten for AgentCore. The starter had not. CloudFormation 模板没有创建说明文档中承诺的任何 IAM 角色。requirements.txtboto3 锁定在 1.42.54 版本,而 AgentCore API 需要 1.43 或更高版本。最后这一点是关键线索:版本锁定低于所需 API 的最低要求,意味着这个代码包比它声称要构建的东西还要老。说明文档已经为 AgentCore 重写了,但初始文件没有。

A classmate figured out why and posted it: the workspace was serving seven outdated files, and the official GitHub repo had been updated with the correct twelve. That one post saved me hours. Whoever you are, thank you, and this is exactly why I write these. I want to be honest that I did not spot this alone and I did not spot it fast. I spent real time building plans on top of a starter I had only partially seen, which is its own lesson about verifying your inputs before designing around them. 一位同学发现了原因并发布了出来:工作区提供了七个过时的文件,而官方 GitHub 仓库已经更新为正确的十二个文件。那条帖子为我节省了数小时。无论你是谁,谢谢你,这也是我写这些文章的原因。我想诚实地说,我不是独自发现的,也没能快速发现。我花了不少时间在只看了一半的初始代码上制定计划,这本身就是一堂课:在围绕输入进行设计之前,必须先验证输入。

A checkpoint you can describe is a checkpoint an agent can fake. This one changed how I run these builds. I gave my build agent a gated plan with QA checkpoints. One of them read: “a bug conversation shows the [tool call] bugreports___create_bug_report line in the transcript.” The agent marked it complete. The script that produces that transcript did not exist in the folder yet. It could not have run. Not once. 一个可以被描述出来的检查点,就是智能体可以伪造的检查点。这一点改变了我进行构建的方式。我给我的构建智能体制定了一个带有质量保证(QA)检查点的分阶段计划。其中一个检查点写着:“错误对话在记录中显示 [tool call] bugreports___create_bug_report 行。”智能体将其标记为已完成。但生成该记录的脚本当时甚至还没在文件夹里,它根本不可能运行过,一次都没有。

Nothing lied to me. A checkpoint written as a description of a desired state is something a language model can reason its way toward. It reads “a bug conversation shows the tool call line,” it considers the prompt it just wrote, it concludes yes, that prompt would produce that, and it ticks the box in good faith. The checkpoint was not false. It was untestable. 没有任何东西在对我撒谎。以“期望状态描述”形式编写的检查点,是语言模型可以通过推理来“达成”的。它读到“错误对话显示工具调用行”,它审视自己刚写的提示词,得出结论:是的,这个提示词会产生那样的结果,于是它问心无愧地勾选了复选框。检查点本身并不虚假,只是无法验证。

A checkpoint written as a command plus its actual pasted output cannot be faked that way. Either it ran or it errored. So I changed the rule. A checkpoint is a command and its output. If you cannot paste the output, it did not pass. Every [x] after that had a terminal transcript attached to it. 以“命令 + 实际粘贴输出”形式编写的检查点就无法这样伪造。要么运行成功,要么报错。所以我改变了规则:检查点必须包含命令及其输出。如果无法粘贴输出,就不算通过。此后,每一个 [x] 后面都附带了终端运行记录。

The same failure showed up somewhere else, wearing different clothes. My spec listed “redirect to a human support phone line” as a requirement but never said where the phone number comes from. Nothing in the course materials supplies one. So the agent generated a plausible one and dropped it into the prompt, three test expectations, and the README. It filled the silence, because that is what these systems do with an unspecified detail. My spec created the gap. 同样的失败以不同的形式出现在其他地方。我的规范要求“转接至人工支持电话”,但从未说明电话号码从何而来。课程材料中也没有提供。于是智能体生成了一个看起来合理的号码,并将其填入提示词、三个测试预期以及 README 中。它填补了空白,因为这就是这些系统处理未定义细节的方式。是我的规范制造了漏洞。

A definition ate itself, and it got past two of us. This was a three-way build. Kiro handled the code and the AWS pipeline. Claude handled architecture review and defect analysis. I directed, validated, and decided. The most useful bug in the whole project did not belong to any one of us. It belonged to the seam between us. 一个定义“吞噬”了自身,而且我们两个人都没发现。这是一个三方协作构建:Kiro 负责代码和 AWS 流水线,Claude 负责架构审查和缺陷分析,我负责指挥、验证和决策。整个项目中最有用的 Bug 不属于我们中的任何一个人,它属于我们协作之间的缝隙。

Kiro drafted the first system prompt. It defined the FAQ route as “the customer asks about a platform topic AND the FAQ contains an answer.” The problem is the word AND. If the FAQ does not contain the answer, the message is not an FAQ question at all. It falls through to the catch-all route, which meant the carefully written rules sitting inside the FAQ route for handling uncovered questions could never fire. Kiro 起草了第一个系统提示词。它将 FAQ 路由定义为“客户询问平台主题 且 FAQ 包含答案”。问题就在于“且”这个词。如果 FAQ 不包含答案,那它根本就不算 FAQ 问题。它会落入兜底路由,这意味着 FAQ 路由中为处理未覆盖问题而精心编写的规则永远不会触发。

Two separately graded behaviors were quietly collapsing into one. No error. No crash. Two test cases just returned suspiciously similar answers. I read that prompt and approved it. The first evaluation run scored it without complaint. It took a separate review pass, Claude reading the prompt line by line against the rubric criteria, to notice what was wrong. 两个本应分开评分的行为悄无声息地合并成了一个。没有报错,没有崩溃,只是两个测试用例返回了极其相似的答案。我读了那个提示词并批准了它。第一次评估运行也没有提出异议。直到进行了一次单独的审查,Claude 对照评分标准逐行阅读提示词,才发现了问题所在。

The fix was one line: classify by the topic of the question, not by whether the answer exists. Uncovered questions became reachable and the bot went from two visible behaviors to three. I have reviewed enough conditional logic to recognize that mistake on sight in code. Dressed as a plain English sentence, it walked right past me. Other things we got to watch fail, which is its own curriculum. The bot answered a… 修复方法只有一行:根据问题的“主题”进行分类,而不是根据“答案是否存在”。未覆盖的问题变得可触达,机器人的可见行为从两种变成了三种。我审查过足够多的条件逻辑,在代码中一眼就能认出这种错误。但当它伪装成一句简单的英语句子时,它就从我眼皮底下溜走了。我们还观察到了其他失败案例,这本身就是一种课程。机器人回答了一个……