Skip to content

Code-along 2024-08-20 Building Trustworthy AI with Agents

Building Trustworthy AI with Agents

Welcome to this Responsible AI tutorial by Theoriq, where we explore the future of AI through the lens of agentic systems or multi-agent systems. As AI agents play an increasingly central role in automating decisions and tasks, the need for responsible AI and robust governance is more critical than ever.

This tutorial is a simulation of a multi-agent system designed to demonstrate how AI agents collaborate and contribute to a collective, concepts covered in the Theoriq Litepaper (2024) (Invalid URL) Learners will see how to build and manage AI agents, highlighting the need for these systems to operate ethically and securely. The future is indeed agentic, and with it comes the responsibility to develop AI that is both powerful and trustworthy.

Lesson Overview

This interactive lesson is designed to teach learners how to build, manage, and govern AI agents in three distinct chapters.

  1. ItineraryPlanner: Generates a travel itinerary based on user input using Claude.
  2. BookingAgent: Simulates the booking process based on the itinerary.
  3. PaymentAgent: Simulates processing payments for the bookings.

Learners will need an API key from Anthropic to access the Claude language model (LLM), which is required to generate AI responses and demonstrate real-world agent interactions. Additionally, a basic understanding of Python is recommended, as the lesson involves editing and running Python code. Other LLM models may be used e.g., Claude 3 or other LLM providers may be called for the AI functionality e.g., OpenAI's GPT4o model. Note, calling these models may require slightly different code, refer to the LLM documentation for instructions.

Chapter 1: Intro to Agents - Building Your First Agent

In Chapter 1, we start by creating a basic AI agent using Python. The Claude LLM is used to develop an Itinerary Planner based on user input. This chapter introduces learners to the fundamentals of AI agents, their specific prompting, and how they can be customized to serve different purposes.

Chapter 2: Intro to Multi-Agent Systems (Collectives) - How Agents Collaborate

In Chapter 2, Learners explore multi-agent systems where multiple AI agents work together to complete a task. We learn how to use a central controller (TaskManager) to coordinate agent activities, such as booking travel and accommodation based on the itinerary generated in Chapter 1. This chapter demonstrates the dynamic flow of information between agents, ensuring seamless task completion.

Chapter 3: Multi-Agent Governance - Building Trustworthy AI with Agents

Chapter 3 focuses on the critical role of governance in AI systems. You’ll implement a governance manager to evaluate multiple payment agents, automatically rejecting those with security issues and approving a secure agent for final digital payment processing. We touch on the notion of provenance, demonstrated through the passing of data securely across chapters, and in Chapter 3 where the AI Evaluation Agent tracks and records the decision-making process, ensuring transparency and accountability in the evaluation of payment agents. This chapter emphasizes the importance of responsible AI, highlighting the need for secure and reliable agent performance.

Throughout the lesson, learners will write and run Python code, making it essential to have a basic understanding of the language. The use of an API key from Anthropic is crucial for accessing the LLM, which powers the AI agents. By the end of this lesson, learners will have gained practical experience in building, coordinating, and governing AI agents that are effective and more trustworthy.

Instructions

API Key

For this lesson we need the an api key and anthropic Python packages in order to access the large language model. This API Key must be added as an Environment Variable in the programming environment. The API Key is a secret and must be stored securely as API calls often come with charges that vary depending on the model used.

For up to date information on calling the Claude model, refer to the most up to date documentation: https://docs.anthropic.com/en/docs/quickstart#call-the-api

Note, Anthropic has very sophisticated models, for the purposes of this lesson, we are using a basic low cost model, Claude 2.

To obtain and use an Anthropic API key follow these steps:

  • sign up for a free account by clicking on 'Try Claude': https://www.anthropic.com/claude
  • once you have an account, navigate to the 'Create an API key' page
  • name your key and copy it
  • within this platform, navigate to the 'Environment' tab and
  • save your API Key as an Environment Variable

We can now call the API key into your programming notebook and use it to access a Claude model.

Instructions

  1. Run the code in this notebook to complete the lesson
  2. Read the code notes preceded by a # in Python to know what the code block is doing
  3. When you have completed all 3 chapters, edit the code to see how that changes your outputs

Chapter 1: Intro to Agents - Building Your First Agent

Objective:

In this chapter, we create a basic AI agent using Python, integrating the Claude model from Anthropic to generate a detailed travel itinerary based on user input.

Setup: Before running the code, ensure you have your Anthropic API key stored securely as an Environment variable.

When the code is run, a user interacts with the agent to generate travel itineraries based on their input. By selecting between different types of trips (e.g., "Young at Heart Adventure," "Family Friendly with Kids," etc.), learners see how agents take on different roles and can be specialized to serve different purposes.

Agent Interaction:

The LLM (Claude) acts as an agent that processes a user’s input and generates a response based on that input. This simulates how AI agents operate in real-world applications, where they process information, make decisions, and provide outputs for a particular task. The code also introduces the concept of routing to different agents based on the user's choices, which is a key aspect of dynamic multi-agent systems.

# Chapter 1: Building a Simple AI Agent

# Step 1: Install and Import Necessary Libraries
!pip install anthropic
from anthropic import Anthropic, HUMAN_PROMPT, AI_PROMPT
import random
import os

api_key = os.environ["ClaudeKey_Tutorial"] # Accessing your API Key from the Environment Variables

# Initialize the Anthropic client
client = Anthropic(api_key=api_key)

def get_claude_response(prompt):
    response = client.completions.create(
        model="claude-2.1",
        prompt=f"{HUMAN_PROMPT} {prompt}{AI_PROMPT}",
        max_tokens_to_sample=2000,
        temperature=0.7,
    )
    return response.completion

# Note that the code is slightly different for more advanced Claude models, refer to Anthropic documentation

Chapter 1 Code Breakdown:

def get_claude_response(prompt): πŸ“

  • This line defines a Python function named get_claude_response. It takes one argument, prompt, which is the input text that will be sent to the Claude model.

response = client.completions.create(: βš™οΈ

  • The client.completions.create method is called to generate a response using the AI model. The result of this method call is stored in the response variable.

model="claude-2.1", πŸ€–

  • This specifies the version of the Claude model to use. In this case, it’s "claude-2.1".

prompt=f"{HUMAN_PROMPT} {prompt}{AI_PROMPT}", πŸ’¬

  • The prompt parameter is a string formatted using an f-string. It constructs the prompt that will be sent to the model by combining the HUMAN_PROMPT, the user's input (prompt), and the AI_PROMPT.
  • HUMAN_PROMPT and AI_PROMPT, constants or variables that define the typical structure of a conversation between a user and the AI, framing the input and output context.

max_tokens_to_sample=2000, ✍️

  • This argument controls the maximum number of tokens (words or symbols) that the model will generate in its output. Here, it’s set to 2000, meaning the response will be capped at this length.

temperature=0.7, 🌑️

  • The temperature parameter controls the randomness of the model's output. A temperature of 0.7 strikes a balance between creativity and determinism. Lower values like 0.2 would make the output more predictable, while higher values like 1.0 would make it more diverse and creative.

return response.completion: βœ…

  • This line returns the actual generated text (often called a "completion") from the response object. The function returns this value to wherever get_claude_response was called, so it can be used or displayed as needed.
# Test API and LLM connection 
# Use the LLM to generate text
response = get_claude_response("Write a haiku about a travel")

print(response)

Reminder: What is an Agent?

β€œAI agents are autonomous software systems that leverage modern generative AI models to plan, access data, use tools, make decisions, and interact with the real world to perform specific functions.” -- Theoriq AI Agent Base Layer, Theoriq Litepaper (2024)

With the debut of accessible LLMs and the popularity of no-code builders, most of us will be building our agents to replace paid software in the not too distant future. If the future is truly agentic, let's get to know how agents work and how to manage them.

Introduction to Agents

In this step we will collect user input that will be used by our itinerary agent.

# Introduction to Agents

# Step 3: Define a Function to Collect and Validate User Input
class UserInput:
    def __init__(self, departure_location, location, people_count, travel_days, travel_month, audience_choice, budget):
        self.departure_location = departure_location
        self.location = location
        self.people_count = people_count
        self.travel_days = travel_days
        self.travel_month = travel_month
        self.audience_choice = audience_choice
        self.budget = budget

def validate_city_input(city):
    # A simple validation to check if the city input contains numbers or special characters
    if not city.replace(' ', '').isalpha():
        return False
    return True

def validate_numeric_input(value, input_type):
    try:
        num = int(value)
        if num <= 0:
            raise ValueError
        return num
    except ValueError:
        print(f"Invalid input for {input_type}. Please enter a positive integer. Currency is in USD. ")
        return None

def ask_user_questions():
    while True:
        departure_location = input("What city and country are you traveling from? (e.g., Toronto or Toronto Canada.) ")
        if validate_city_input(departure_location):
            break
        else:
            print("Invalid city name. Please enter a valid city and country (e.g., Toronto or Toronto Canada.) ")

    while True:
        location = input("What is your city and country destination? (e.g., London or London UK.) ")
        if validate_city_input(location):
            break
        else:
            print("Invalid city name. Please enter a valid city and country (e.g., London or London UK.) ")

    while True:
        if location.lower() == departure_location.lower():
            print("Destination cannot be the same as departure location. Please choose a different destination.")
            location = input("What is your city and country destination? ")
        else:
            break

    while True:
        people_count = validate_numeric_input(input("How many people are traveling? "), "number of people")
        if people_count is not None:
            break

    while True:
        travel_days = validate_numeric_input(input("How many days are you traveling for? "), "number of days")
        if travel_days is not None:
            break

    travel_month = input("What month are you traveling? ")

    while True:
        audience_choice = input("What type of trip would you like: \n(1: Young at Heart Adventure πŸ•Ί πŸͺ‚, 2: Family Friendly with Kids πŸ§‘β€πŸ§‘β€πŸ§’β€πŸ§’ 🍼, 3: Elderly Inclusive πŸ‘΅ πŸ‘¨β€πŸ¦½β€βž‘οΈ) \n-> Enter # 1, 2, or 3 now: ")
        if audience_choice in ["1", "2", "3"]:
            break
        else:
            print("Invalid input. Please enter 1, 2, or 3.")

    while True:
        budget = validate_numeric_input(input("What is your budget in USD? (enter an integer e.g., 1000) "), "budget")
        if budget is not None:
            break

    # Map the audience choice to a descriptive label
    audience_map = {
        "1": "Young at Heart Adventure πŸ•Ί πŸͺ‚ ",
        "2": "Family Friendly with Kids πŸ§‘β€πŸ§‘β€πŸ§’β€πŸ§’ 🍼 ",
        "3": "Elderly Inclusive πŸ‘΅ πŸ‘¨β€πŸ¦½β€βž‘οΈ "
    }
    audience_choice = audience_map.get(audience_choice, "Unknown")

    # Create a UserInput object with the validated answers
    return UserInput(departure_location, location, people_count, travel_days, travel_month, audience_choice, budget)

# Step 4: Define the Router to Choose the Appropriate Agent
def choose_agent(user_input):
    audience_choice = user_input.audience_choice
    if audience_choice == "Young at Heart Adventure πŸ•Ί πŸͺ‚ ":
        return agent_young_and_fun
    elif audience_choice == "Family Friendly with Kids πŸ§‘β€πŸ§‘β€πŸ§’β€πŸ§’ 🍼 ":
        return agent_family_friendly
    elif audience_choice == "Elderly Inclusive πŸ‘΅ πŸ‘¨β€πŸ¦½β€βž‘οΈ ":
        return agent_elderly_inclusive
    else:
        raise ValueError("Invalid audience choice.")

# Step 5: Define the Itinerary Agents
def agent_young_and_fun(user_input):
    prompt = f"""
    You're an expert travel planner. A user has provided the following details for their trip:
    - Departure Location: {user_input.departure_location}
    - Travel Month: {user_input.travel_month}
    - Number of People: {user_input.people_count}
    - Travel Days: {user_input.travel_days}
    - Audience: {user_input.audience_choice}
    - Location: {user_input.location}
    - Budget in USD: {user_input.budget}

    Create a fun and adventurous holiday itinerary for a group of young at heart, risk-taking travelers.
    """
    return get_claude_response(prompt)

def agent_family_friendly(user_input):
    prompt = f"""
    You're an expert travel planner. A user has provided the following details for their trip:
    - Departure Location: {user_input.departure_location}
    - Travel Month: {user_input.travel_month}
    - Number of People: {user_input.people_count}
    - Travel Days: {user_input.travel_days}
    - Audience: {user_input.audience_choice}
    - Location: {user_input.location}
    - Budget in USD: {user_input.budget}

    Create a family-friendly holiday itinerary that includes child-friendly activities, safety, and inclusivity.
    """
    return get_claude_response(prompt)

def agent_elderly_inclusive(user_input):
    prompt = f"""
    You're an expert travel planner. A user has provided the following details for their trip:
    - Departure Location: {user_input.departure_location}
    - Travel Month: {user_input.travel_month}
    - Number of People: {user_input.people_count}
    - Travel Days: {user_input.travel_days}
    - Audience: {user_input.audience_choice}
    - Location: {user_input.location}
    - Budget in USD: {user_input.budget}

    Create an elderly-inclusive holiday itinerary that focuses on safety, accessibility, comfort, and inclusivity for a mature audience.
    """
    return get_claude_response(prompt)

# Step 6: Main Function to Run the Workflow
def main():
    print("πŸ€– Welcome to the Trip Planning AI Agent Collective! 🌐")

    # Collect user inputs
    user_input = ask_user_questions()

    # Route the user input to the appropriate agent
    selected_agent = choose_agent(user_input)

    # Generate the itinerary using the selected agent
    itinerary = selected_agent(user_input)
    print("\nπŸ“‹ Generated Itinerary:")
    print(itinerary)

    # Store the generated itinerary for use in Chapter 2
    return itinerary, user_input

# Run the main function and store the generated itinerary and user input
if __name__ == "__main__":
    generated_itinerary, user_input = main()

Hint!

`Customize the itinerary agent!`

  • Note the defined persona for agent_young_and_fun.

  • This agent is defined by this prompt Create a fun and adventurous holiday itinerary for a group of young at heart, risk-taking travelers. - you can update this and the other personas to suit your preferred trip experiences.

Chapter 1 Completed!

Congratulations, you have built your first agent!

  • Based on user input, this agent was able to create an itinerary for a trip.
  • Some consider the different trip experiences 3 different agents but since their intended task is the same, to plan an itinerary, we will refer to this as one agent. E.g.,

πŸ“‹ Generated Itinerary: Here is a 7-day family-friendly holiday itinerary for 3 people traveling from Toronto to Sao Paulo in December on a $4,000 USD budget

  • πŸ€– You can see how agents can have specializations in a particular type of itinerary and the user input gets routed to the appropriate agent based on their preferred trip details.
  • 🚨 NOTE: This code uses a live LLM interaction to produce a response so results may vary and while we have included some data entry validation measures, users may attempt to enter alternative forms of cities or other inputs.
  • ⛓️‍πŸ’₯ Deliberatly trying to get an LLM to 'break' is called 'JailBreaking'!.
β€Œ
β€Œ
β€Œ