Well, I'm back, although it took slightly longer than I expected, so the run that I had just kicked 嗯，我回来了，虽然比我预想的要长一些，所以我刚刚踢的跑步
off actually ended up taking several minutes, and it appeared to lose its way. 结果实际上花了几分钟，而且它似乎迷了路。
Going back again and again to get more and more emails generated. 一次又一次地返回以生成越来越多的电子邮件。
So I actually cancelled it and ran it a second time and it ran fine. 所以我实际上取消了它并第二次运行它并且运行良好。
But it is interesting. 但这很有趣。
It's a it's a cautionary tale to reflect on the fact that by their very nature, these autonomous agents 这是一个警示故事，让我们反思这样一个事实：从本质上来说，这些自主代理
are made. 被制作。
This statement here, and this was the answer to the, the challenge from from last time that I say 这里的声明，这是对我上次所说的挑战的答案
you can use the tools multiple times if you're not satisfied with the results. 如果您对结果不满意，可以多次使用这些工具。
And that's really giving this kind of autonomy and potentially an infinite loop to the agent. 这确实为代理提供了这种自主权和潜在的无限循环。
And sure enough, we I don't know if it was infinite, but we certainly had some kind of a loop going 果然，我们不知道它是否是无限的，但我们肯定有某种循环在进行
on. 在。
But I ran it a second time and it was fine. 但我又跑了第二次，就很好了。
If I bring up the trace, here come the traces. 如果我提出痕迹，痕迹就来了。
This this is the one that was going wrong. 这就是出了问题的地方。
You can see it had run 14 tools and it was taking more than 300 seconds. 您可以看到它运行了 14 个工具，并且花费了超过 300 秒的时间。
If I bring it up, you'll see that it was going through sales agents one, two and three and then back 如果我提起它，您会发现它正在通过销售代理一、二和三，然后返回
to one, two and three again. 又到一、二、三。
And I can load more and on. 我还可以加载更多内容。
So it kept going. 所以它继续下去。
Now you'll see, of course, that agent one is deep seek. 现在您当然会看到，第一个代理正在深度寻找。
Agent two is Gemini. 二号经纪人是双子座。
Agent three is llama 3.3. 三号代理是 llama 3.3。
One other thing that I didn't point out last time that I would like to mention is that you can see that 上次我没有指出但我想提的另一件事是你可以看到
these are running in parallel. 这些是并行运行的。
They are running, of course asynchronously because again, because they're very I o bound, they are 它们当然是异步运行的，因为它们非常受限制，它们是
doing they're waiting for information to come back from the API call that allows async IO to be running 他们正在等待从允许异步 IO 运行的 API 调用返回的信息
multiple in parallel. 多个并联。
But of course the three run and then it needs to sort of wait for. 但当然，这三个人都跑了，然后需要等待。
Then the sales manager will review those three runs and decide whether it wants to run them again, 然后销售经理将审查这三轮运行并决定是否要再次运行它们，
which apparently it did lots of times. 显然它已经做了很多次了。
And llama 3.3 for some reason took a really long time on one of them. 由于某种原因，llama 3.3 在其中一个上花了很长时间。
So you can see there is inherent instability with these autonomous agent frameworks. 所以你可以看到这些自主代理框架存在固有的不稳定性。
And that's something that you need to code explicitly for. 这就是您需要明确编码的内容。
Four. 四。
Okay, but now let's just go back and look at the trace that did better. 好的，但现在让我们回过头来看看效果更好的跟踪。
So this is the trace that just ran. 这就是刚刚运行的跟踪。
And it took a rather more pleasing amount of time. 这花费了相当令人愉快的时间。
And you can see that this time it only ran each agent once. 您可以看到，这次每个代理只运行一次。
Deep seek Gemini and Llama 3.3. 深寻双子座和骆驼3.3。
Each one ran. 一个个都跑了。
Each one came back with a response. 每个人都带着回应回来了。
That response was of course went to our handoff, went to the email manager that wrote the subject, 该回复当然会发送给我们，发送给撰写该主题的电子邮件管理器，
wrote the email, and then an email arrived right here in my inbox. 写了电子邮件，然后一封电子邮件就到达了我的收件箱。
So all has worked well in the end. 所以最终一切都很顺利。
So I went through that code very fast because it's something that we saw before yesterday, so hopefully 所以我很快地浏览了这段代码，因为这是我们昨天之前看到的，所以希望
it was somewhat familiar. 这有点熟悉。
The new angle was that we were calling multiple models, and it was very easy because they are all models 新的角度是我们调用多个模型，这很容易，因为它们都是模型
which have OpenAI compatible endpoints. 具有 OpenAI 兼容端点。
Now, you may have noticed that there is one model that was missing there in the form of Anthropic's 现在，您可能已经注意到，其中缺少一个模型，即 Anthropic 的形式
Claude and anthropic does not offer an OpenAI compatible endpoint. Claude 和 anthropic 不提供 OpenAI 兼容端点。
And so I understand that there isn't, as of today, an easy way to use Anthropic's Claude in lieu of 所以我明白，截至今天，还没有一种简单的方法可以使用 Anthropic 的 Claude 来代替
those other models that have an OpenAI compatible endpoint. 具有 OpenAI 兼容端点的其他模型。
But there are plenty of workarounds. 但有很多解决方法。
So there is, for example, a third party provider called Open Router that people are probably a lot 例如，有一个名为 Open Router 的第三方提供商，人们可能很多
of people use that, and it allows you to to set up your keys for other models, including Anthropic's 的人使用它，它允许您为其他模型设置密钥，包括 Anthropic 的
Claude. 克劳德.
And it has an open AI compatible endpoint. 它有一个开放的人工智能兼容端点。
So you can go through open router to use Claude. 所以你可以通过开放路由器来使用Claude。
Also, anthropic has the incredible MCP protocol, which we'll be talking about in the last week. 另外，anthropic 有令人难以置信的 MCP 协议，我们将在上周讨论它。
And that gives us another route to be using anthropic through MCP. 这为我们提供了通过 MCP 使用人择的另一条途径。
So more will come on that later. 所以稍后会有更多内容。
In the meantime, the easiest way to do this is to use models other than anthropic for this purpose. 同时，最简单的方法是使用人择模型以外的模型来实现此目的。
And perhaps quite soon Anthropic's Claude will be available through the OpenAI SDK direct. 也许很快 Anthropic 的 Claude 将可以通过 OpenAI SDK 直接使用。
Anyway, the next thing we're going to do is talk about both structured outputs and guardrails. 不管怎样，我们接下来要做的就是讨论结构化输出和护栏。
We're going to do them together Other, and guardrails are ways that you can put a constraint around 我们要一起做其他的，护栏是你可以施加约束的方式
your agent platform. 您的代理平台。
It's a test that you will do. 这是你要做的一个测试。
And the cool thing about guardrails, I mean, you might think if guardrails were simply like a check 我的意思是，关于护栏的最酷的事情，你可能会认为护栏是否只是像一张支票
of, of like, um, checking that something has given the right kind of results, you could just write 的，就像，嗯，检查某些东西是否给出了正确的结果，你可以这样写
that in Python code. Python 代码中的内容。
You can just obviously look test whether the results have a certain property in them or not, and throw 您可以明显地查看测试结果是否具有某种属性，然后抛出
an exception if they don't. 如果他们不这样做，则例外。
The special thing about guardrails here is that guardrails can themselves be agents, which means that 这里护栏的特别之处在于护栏本身可以是代理，这意味着
you can use an LLM to be checking that things look good at any point in your flow. 您可以使用法学硕士来检查流程中任何一点的情况是否良好。
Well, actually, that's not quite true. 嗯，实际上，这并不完全正确。
When I say at any point, guardrails actually can only be applied either to the input at the very beginning, 当我说在任何时候，护栏实际上只能应用于一开始的输入，
the input of the first agent or the output of the last agent. 第一个智能体的输入或最后一个智能体的输出。
You can't insert guardrails all over the place. 不能到处都加护栏。
You just have them at the very beginning or the very end. 你只是在开始或结束时拥有它们。
And they're designed to protect your model against getting an input, which is inappropriate or not. 它们旨在保护您的模型免受不适当或不适当的输入。
Not what it's intended for. 不是它的目的。
And also to protect it against producing an output which should not be shown to the user. 并且还可以防止它产生不应向用户显示的输出。
So it's those two extremes. 所以这是两个极端。
That's where you can implement guardrails. 这就是您可以实施护栏的地方。
And we're going to implement an input guardrail right now. 我们现在要实施一个输入护栏。
But as you'll see it's it's basically exactly the same thing either way. 但正如您将看到的，无论哪种方式，基本上都是完全相同的。
And I'll leave a challenge for you to add an output one afterwards. 我将给你留下一个挑战，让你在之后添加一个输出。
So the first thing I do because we're going to be working with structured outputs is I define an a class 所以我做的第一件事是定义一个 a 类，因为我们将使用结构化输出
called name check output. 称为名称检查输出。
We're going to be saying we're going to be checking for names for people's names because we don't want 我们会说我们要检查人们的名字，因为我们不想
people's names in our emails. 我们的电子邮件中的人员姓名。
We decided so we're going to have a name check output. 我们决定，我们将有一个名称检查输出。
And this is one of these pedantic objects. 这就是这些迂腐的东西之一。
If you remember, this is where you have objects classes which are designed to reflect a particular 如果您还记得的话，这就是您拥有旨在反映特定对象的对象类的地方。
schema of data. 数据模式。
So what we want is that we want the name check output to be something which has two fields is name in 所以我们想要的是，我们希望名称检查输出具有两个字段： name in
message, which is a boolean where true should mean that there is a name in this message and name. message，这是一个布尔值，其中 true 应该意味着此消息和名称中有一个名称。
A string would be the name if there is a name in the message. 如果消息中有名称，则字符串将是名称。
Okay, so this is all we're doing here is we're sort of defining we're defining a schema. 好的，这就是我们在这里所做的一切，我们正在定义一个模式。
We're saying this is a particular structure of class that we want to to think of. 我们说这是我们想要考虑的特定类结构。
And now we're going to define an agent. 现在我们要定义一个代理。
And I'm naming it guardrail agent. 我将其命名为护栏代理。
You can name it whatever you want. 您可以将其命名为任何您想要的名称。
We are going to use this in a guardrail. 我们将在护栏中使用它。
But this is just as of now just another agent we're creating. 但这只是我们现在正在创建的另一个代理。
It's name is going to be name check. 其名称将进行名称检查。
The instructions are check if the user is including someone's personal name in what they want you to 这些说明是检查用户是否在他们希望您添加的内容中包含某人的个人姓名
do. 做。
The output type this. 输出类型为this。
This is the structured outputs piece. 这是结构化输出部分。
We are telling this agent we don't want you to output text, which is what you normally do by default. 我们告诉该代理我们不希望您输出文本，这是您通常默认执行的操作。
All of these are outputting just strings of data, but rather we want you to output a name check output. 所有这些都仅输出数据字符串，但我们希望您输出名称检查输出。
We want you to output an object that conforms to this schema. 我们希望您输出符合此架构的对象。
And you can use this for any of your agents. 您可以将其用于您的任何代理。
So we could go back and use this as a way to structure our emails better. 所以我们可以回去使用它来更好地构建我们的电子邮件。
So we could use this so that rather than emails being just strings, they could actually already have 所以我们可以使用它，这样电子邮件就不再只是字符串，而是实际上已经有了
a subject, a recipient, a body. 主体、接受者、身体。
We could do it that way from the get go. 我们可以从一开始就这样做。
And that would be much nicer. 那会好得多。
And that is in the challenges at the end. 这就是最后的挑战。
But for here we specify the output type is name check output. 但这里我们指定输出类型是名称检查输出。
And as before we specify a model GPT four mini. 和之前一样，我们指定了 GPT 4 mini 型号。
And that brings us simply to the guardrail. 这就把我们带到了护栏上。
So a guardrail is it's like an asynchronous. 所以护栏就像是异步的。
It's a coroutine. 这是一个协程。
It's going to say a function. 它会说一个函数。
But it is of course strictly speaking a coroutine. 但严格来说它当然是一个协程。
And you simply decorate it with input guardrail to say, I'm going to be using this as an input guardrail. 你只需用输入护栏装饰它，就可以说，我将使用它作为输入护栏。
It's a bit like decorating something to be a tool. 这有点像装饰某物以使其成为工具。
And there's a completely analogous one called output guardrail, which is what you would use if it was 还有一种完全类似的称为输出护栏，如果它是
to be used as a guardrail for the output. 用作输出的护栏。
You can call it whatever you want and it takes the context is a bunch of data that you can pass between 你可以随意称呼它，它的上下文是一堆你可以在之间传递的数据
agents that we we haven't made use of the agent itself. 代理我们还没有使用代理本身。
And this is the input, the input that's coming in. 这就是输入，即将到来的输入。
I've called it message. 我把它称为消息。
And so what we can do right here is we can as part of implementing this guardrail, we can actually 所以我们在这里可以做的是，作为实施这个护栏的一部分，我们实际上可以
kick off this guardrail agent. 踢掉这个护栏代理。
We can run this guardrail agent. 我们可以运行这个护栏代理。
And it will it will be giving it these instructions. 它将给予它这些指示。
It will be passing in the message and it will be expecting a name check output to come out of that. 它将传入消息，并期望从中产生名称检查输出。
So this is basically going to do just what it says on the tin. 所以这基本上就是按照罐头上说的做的。
It's going to check if someone's personal name is being included in the message. 它将检查消息中是否包含某人的个人姓名。
And then you have to return that the rule about writing these guardrails is you have to return something 然后你必须返回编写这些护栏的规则是你必须返回一些东西
called a guardrail function output. 称为护栏函数输出。
That's that's always a thing you return, which is informing the system whether or not there is a problem. 这就是您始终返回的东西，即通知系统是否存在问题。
And it has two, two things. 它有两件事。
Output info is just a dictionary of stuff that might be useful for tracing and trip wire triggered is 输出信息只是可能对跟踪有用的内容的字典，触发的绊线是
a boolean. 一个布尔值。
It's true. 这是真的。
If there's a problem you pass in true here. 如果有问题你可以在这里传递 true 。
If something has happened which should trip the trip wire and alert the guardrail has not been met. 如果发生了一些事情，应该触发绊线并警告护栏没有被碰到。
And there is a problem. 但有一个问题。
So what we're doing here is we're saying if this agent that we just ran, this agent produced an object 所以我们在这里所做的是，如果我们刚刚运行的代理生成了一个对象
of type name check output, if that has is name and message set to true, which means that this agent 类型名称检查输出，如果名称和消息设置为 true，则意味着该代理
reckons that there's someone's personal name in the instructions, then that should trigger the trip 认为说明中有某人的个人姓名，那么应该会触发行程
wire. 金属丝。
That should cause this guardrail to fail. 这应该会导致这个护栏失效。
And there should be a problem. 而且应该有问题。
That's that's the key. 这就是关键。
That's how it works. 这就是它的工作原理。
I hope that makes sense. 我希望这是有道理的。
And you could use exactly this structure. 你完全可以使用这个结构。
And then of course, for output guardrails, it's pretty much the same thing. 当然，对于输出护栏来说，这几乎是一样的。
But instead of message you would put the output there. 但您可以将输出放在那里，而不是消息。
Otherwise exactly the same. 否则完全一样。
All right let's give this a try. 好吧，让我们尝试一下。