Skip to content

Guardrails

Guardrails(防護欄)會與你的代理(Agent)_並行_運作,讓你能夠對使用者輸入進行檢查與驗證。例如,假設你有一個代理(Agent)使用非常聰明(因此也較慢或昂貴)的模型來協助處理客戶請求。你不會希望惡意使用者要求該模型協助他們完成數學作業。因此,你可以使用一個快速/低成本的模型來執行 guardrail。如果 guardrail 偵測到惡意使用行為,它可以立即拋出錯誤,從而阻止昂貴的模型執行,幫你節省時間與金錢。

Guardrails 有兩種類型:

  1. Input guardrails(輸入防護欄):在使用者最初輸入時執行
  2. Output guardrails(輸出防護欄):在代理(Agent)最終輸出時執行

Input guardrails(輸入防護欄)

Input guardrails(輸入防護欄)會經過三個步驟:

  1. 首先,guardrail 會接收到與代理(Agent)相同的輸入。
  2. 接著,guardrail 函式會執行,產生一個 [GuardrailFunctionOutput][agents.guardrail.GuardrailFunctionOutput],然後包裝成一個 [InputGuardrailResult][agents.guardrail.InputGuardrailResult]
  3. 最後,我們會檢查 [.tripwire_triggered][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] 是否為 true。如果為 true,則會拋出 [InputGuardrailTripwireTriggered][agents.exceptions.InputGuardrailTripwireTriggered] 例外,你可以適當地回應使用者或處理該例外狀況。

Note

Input guardrails(輸入防護措施)是設計用來運行於使用者輸入上的,因此一個 Agent 的 guardrails 僅會在該 Agent 為第一個 Agent 時執行。你可能會好奇,為什麼 guardrails 屬性會放在 Agent 上,而不是傳遞給 Runner.run?這是因為 guardrails 通常與實際的 Agent 相關——你會針對不同的 Agent 執行不同的 guardrails,因此將程式碼放在一起有助於提升可讀性。

Output guardrails(輸出防護措施)

Output guardrails 的執行分為三個步驟:

  1. 首先,guardrail 會接收由 Agent 產生的輸出。
  2. 接著,guardrail 函式會運行,產生一個 [GuardrailFunctionOutput][agents.guardrail.GuardrailFunctionOutput],然後包裝成一個 [OutputGuardrailResult][agents.guardrail.OutputGuardrailResult]。
  3. 最後,我們會檢查 [.tripwire_triggered][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] 是否為 true。如果為 true,則會拋出一個 [OutputGuardrailTripwireTriggered][agents.exceptions.OutputGuardrailTripwireTriggered] 例外(exception),讓你可以適當地回應使用者或處理該例外狀況。

Note

Output guardrails 旨在運行於最終的 Agent 輸出,因此一個 Agent 的 guardrails 只會在該 Agent 是最後一個 Agent 時執行。這與 input guardrails 類似,原因是 guardrails 通常與實際的 Agent 相關——你會針對不同的 Agent 執行不同的 guardrails,因此將程式碼放在一起有助於提升可讀性。

Tripwires

如果輸入或輸出未通過 guardrail,Guardrail 可以透過 tripwire 來發出訊號。一旦發現有 guardrail 觸發了 tripwires,我們會立即拋出 {Input,Output}GuardrailTripwireTriggered 例外並終止 Agent 執行。

實作 guardrail

你需要提供一個接收輸入並回傳 [GuardrailFunctionOutput][agents.guardrail.GuardrailFunctionOutput] 的函式。在這個範例中,我們會透過在底層執行一個 Agent 來達成這個目的。

from pydantic import BaseModel
from agents import (
    Agent,
    GuardrailFunctionOutput,
    InputGuardrailTripwireTriggered,
    RunContextWrapper,
    Runner,
    TResponseInputItem,
    input_guardrail,
)

class MathHomeworkOutput(BaseModel):
    is_math_homework: bool
    reasoning: str

guardrail_agent = Agent( # (1)!
    name="Guardrail check",
    instructions="Check if the user is asking you to do their math homework.",
    output_type=MathHomeworkOutput,
)


@input_guardrail
async def math_guardrail( # (2)!
    ctx: RunContextWrapper[None], agent: Agent, input: str | list[TResponseInputItem]
) -> GuardrailFunctionOutput:
    result = await Runner.run(guardrail_agent, input, context=ctx.context)

    return GuardrailFunctionOutput(
        output_info=result.final_output, # (3)!
        tripwire_triggered=result.final_output.is_math_homework,
    )


agent = Agent(  # (4)!
    name="Customer support agent",
    instructions="You are a customer support agent. You help customers with their questions.",
    input_guardrails=[math_guardrail],
)

async def main():
    # This should trip the guardrail
    try:
        await Runner.run(agent, "Hello, can you help me solve for x: 2x + 3 = 11?")
        print("Guardrail didn't trip - this is unexpected")

    except InputGuardrailTripwireTriggered:
        print("Math homework guardrail tripped")
  1. 我們會在 guardrail 函式中使用這個 Agent。
  2. 這是 guardrail 函式,會接收 Agent 的輸入或上下文,並回傳結果。
  3. 我們可以在 guardrail 結果中加入額外資訊。
  4. 這是實際定義工作流程的 Agent。

Output guardrails 也類似。

from pydantic import BaseModel
from agents import (
    Agent,
    GuardrailFunctionOutput,
    OutputGuardrailTripwireTriggered,
    RunContextWrapper,
    Runner,
    output_guardrail,
)
class MessageOutput(BaseModel): # (1)!
    response: str

class MathOutput(BaseModel): # (2)!
    reasoning: str
    is_math: bool

guardrail_agent = Agent(
    name="Guardrail check",
    instructions="Check if the output includes any math.",
    output_type=MathOutput,
)

@output_guardrail
async def math_guardrail(  # (3)!
    ctx: RunContextWrapper, agent: Agent, output: MessageOutput
) -> GuardrailFunctionOutput:
    result = await Runner.run(guardrail_agent, output.response, context=ctx.context)

    return GuardrailFunctionOutput(
        output_info=result.final_output,
        tripwire_triggered=result.final_output.is_math,
    )

agent = Agent( # (4)!
    name="Customer support agent",
    instructions="You are a customer support agent. You help customers with their questions.",
    output_guardrails=[math_guardrail],
    output_type=MessageOutput,
)

async def main():
    # This should trip the guardrail
    try:
        await Runner.run(agent, "Hello, can you help me solve for x: 2x + 3 = 11?")
        print("Guardrail didn't trip - this is unexpected")

    except OutputGuardrailTripwireTriggered:
        print("Math output guardrail tripped")
  1. 這是實際 Agent 的輸出型別。
  2. 這是 guardrail 的輸出型別。
  3. 這是 guardrail 函式,會接收 Agent 的輸出並回傳結果。
  4. 這是定義工作流程的實際 Agent。