Lesson 33 of 33 ยท Part 4: Multi-Agent Teams

Code: Guardrails & Human Approval

Check what goes in and out, and ask a human before the agent does anything risky.

Last time: Agents shared a whiteboard: each one read all the notes, then added its own.
Today: Brakes for an agent that acts: check what goes in, ask a human, check what comes out.
Source Code
1# part4/guardrails.py - check what goes in, ask a human first, check what comes out
2import json
3from openai import OpenAI
4client = OpenAI()
5
6# Same helper as before: one agent = one API call with its own system prompt.
7def run_agent(system_prompt, task):
8    response = client.chat.completions.create(
9        model="gpt-4o-mini",
10        messages=[
11            {"role": "system", "content": system_prompt},
12            {"role": "user", "content": task},
13        ],
14    )
15    return response.choices[0].message.content
16
17# A guardrail can be a small agent: Cora answers with one word our code can read.
18checker_prompt = "You are Cora. You check messages for a school helper app. Reply SAFE or UNSAFE only."
19def is_safe(text):
20    verdict = run_agent(checker_prompt, text)
21    return verdict.strip().startswith("SAFE")
22
23# A pretend tool: it only prints. It never really sends anything.
24def send_email(to, body):
25    print(f"๐Ÿ“ง (pretend) Email to {to}: {body}")
26    return "Email sent."
27
28tools = [{"type": "function", "function": {
29    "name": "send_email", "description": "Send an email to someone.",
30    "parameters": {"type": "object", "properties": {
31        "to": {"type": "string", "description": "a name, e.g. Ms. Lee"},
32        "body": {"type": "string"}
33    }, "required": ["to", "body"]}
34}}]
35RISKY_TOOLS = {"send_email"}  # actions a human must say yes to first
36
37max_prompt = "You are Max, a school helper. The student's teacher is Ms. Lee."
38request = "Email my teacher that I finished my science project."
39print("You:", request)
40
41# Gate 1 - input guardrail: Cora checks the request before Max sees it
42if not is_safe(request):
43    print("Sorry, I can't help with that. Let's keep things kind and safe.")
44    raise SystemExit  # stop the program right here
45
46# Max gets the request and his tool menu (one round, like the Part 2 agent)
47messages = [{"role": "system", "content": max_prompt},
48            {"role": "user", "content": request}]
49response = client.chat.completions.create(model="gpt-4o-mini", messages=messages, tools=tools)
50message = response.choices[0].message
51messages.append(message)
52reply = message.content  # his text answer (None if he asks for a tool)
53
54if message.tool_calls:  # Max can only ASK for a tool; our code decides
55    tool_call = message.tool_calls[0]
56    name = tool_call.function.name
57    args = json.loads(tool_call.function.arguments)
58
59    # Gate 2 - human approval: a risky tool waits for a person's yes
60    allowed = True
61    if name in RISKY_TOOLS:
62        answer = input(f"Allow {name} with {args}? (y/n) ")
63        allowed = answer.strip().lower() == "y"
64    if allowed:
65        result = send_email(**args)
66    else:
67        result = "The human said no."
68
69    messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": result})
70    final = client.chat.completions.create(model="gpt-4o-mini", messages=messages)
71    reply = final.choices[0].message.content
72
73# Gate 3 - output guardrail: Cora checks Max's answer before we show it
74if not is_safe(reply):
75    reply = "Sorry, I can't share that answer."
76print("Max:", reply)

No output yet...

โ† Prev
1/0