diff --git a/.env.example b/.env.example
index ad5cffd..2ef8321 100644
--- a/.env.example
+++ b/.env.example
@@ -39,7 +39,7 @@ OPENAI_API_KEY=sk-proj-...
AGENT_GOAL=goal_choose_agent_type # (default)
#Choose which category(ies) of goals you want to be listed by the Agent - options are system (always included), hr, travel, or all.
-GOAL_CATEGORIES=hr,travel # default is all
+GOAL_CATEGORIES=hr,travel,fin # default is all
# Set if the UI should force a user confirmation step or not
SHOW_CONFIRM=True
\ No newline at end of file
diff --git a/README.md b/README.md
index 7650d7d..1a2fad2 100644
--- a/README.md
+++ b/README.md
@@ -9,24 +9,8 @@ It's really helpful to [watch the demo (5 minute YouTube video)](https://www.you
[](https://www.youtube.com/watch?v=GEXllEH2XiQ)
## Why Temporal?
-There are a lot of AI and Agentic AI tools out there, and more on the way. But why Temporal? I asked one of the AI models used in this demo to answer this question (edited minorly):
-
-### Reliability and State Management:
- Temporal ensures durability and fault tolerance, which are critical for agentic AI systems that involve long-running, complex workflows. For example, it preserves application state across failures, allowing AI agents to resume from where they left off without losing progress. Major AI companies use this for research experiments and agentic flows, where reliability is essential for continuous exploration.
-### Handling Complex, Dynamic Workflows:
-Agentic AI often involves unpredictable, multi-step processes like web crawling or data searching. Temporal’s workflow orchestration simplifies managing these tasks by abstracting complexity, providing features like retries, timeouts, and signals/queries. Temporal makes observability and resuming failed complex experiments and deep searches simple.
-### Scalability and Speed:
-Temporal enables rapid development and scaling, crucial for AI systems handling large-scale experiments or production workloads. AI model deployment and SRE teams use it to get code to production quickly with scale as a focus, while research teams can (and do!) run hundreds of experiments daily. Temporal customers report a significant reduction in development time (e.g., 20 weeks to 2 weeks for a feature).
-### Observability and Debugging:
-Agentic AI systems need insight into where processes succeed or fail. Temporal provides end-to-end visibility and durable workflow history, which Temporal customers are using to track agentic flows and understand failure points.
-### Simplified Error Handling:
-Temporal abstracts failure management (e.g., retries, rollbacks) so developers can focus on AI logic rather than "plumbing" code. This is vital for agentic AI, where external interactions (e.g., APIs, data sources) are prone to failure.
-### Flexibility for Experimentation:
-For research-heavy agentic AI, Temporal supports dynamic, code-first workflows and easy integration of new signals/queries, aligning with researchers needs to iterate quickly on experimental paths.
-
-In essence, Temporal’s value lies in its ability to make agentic AI systems more reliable, scalable, and easier to develop by handling the underlying complexity of distributed workflows for both research and applied AI tasks.
-
-Temporal was built to solve the problems of distributed computing, including scalability, reliability, security, visibility, and complexity. Agentic AI systems are complex distributed systems, so Temporal should fit well. Scaling, security, and productionalization are major pain points in March 2025 for building agentic systems.
+There are a lot of AI and Agentic AI tools out there, and more on the way. But why Temporal? Temporal gives this system reliablity, state management, a code-first approach that we really like, built-in observability and easy error handling.
+For more, check out [architecture-decisions](./architecture-decisions.md).
## Setup and Configuration
See [the Setup guide](./setup.md).
diff --git a/adding-goals-and-tools.md b/adding-goals-and-tools.md
index db5878b..68b867f 100644
--- a/adding-goals-and-tools.md
+++ b/adding-goals-and-tools.md
@@ -3,12 +3,20 @@ The agent is set up to allow for multiple goals and to switch back to choosing a
It may be helpful to review the [architecture](./architecture.md) for a guide and definition of goals, tools, etc.
+### Adding a New Goal Category
+Goal Categories lets you pick which groups of goals to show. Set via an .env setting, GOAL_CATEGORIES.
+1. Pick a unique one that has some business meaning
+2. Use it in your .env file
+3. Add to [.env.example](./.env.example)
+4. Use it in your Goal definition, see below.
+
### Adding a Goal
1. Open [/tools/goal_registry.py](tools/goal_registry.py) - this file contains descriptions of goals and the tools used to achieve them
-2. Pick a name for your goal!
+2. Pick a name for your goal! (such as "goal_hr_schedule_pto")
3. Fill out the required elements:
- `id`: needs to be the same as the name
- `agent_name`: user-facing name for the agent/chatbot
+- `category_tag`: category for the goal
- `agent_friendly_description`: user-facing description of what the agent/chatbot does
- `tools`: the list of tools the goal will walk the user through. These will be defined in the [tools/tool_registry.py](tools/tool_registry.py) and should be defined in list form as tool_registry.[name of tool]
- Important! The last tool listed must be `list_agents_tool`. This allows the chatbot to guide the user back to choosing from the list of available goals once a goal is complete.
@@ -44,7 +52,7 @@ description="Help the user gather args for these tools in order: "
2. Define the tool
- `name`: name of the tool - this is the name as defined in the goal description list of tools. The name should be (sort of) the same as the tool name given in the goal description. So, if the description lists "CurrentPTO" as a tool, the name here should be `current_pto_tool`.
- `description`: LLM-facing description of tool
-- `arguments`: These are the _input_ arguments to the tool. Each input argument should be defined as a [/models/tool_definitions.py](ToolArgument). Tools don't have to have arguments but the arguments list has to be declared. If the tool you're creating doesn't have inputs, define arguments as `arguments=[]`
+- `arguments`: These are the _input_ arguments to the tool. Each input argument should be defined as a [ToolArgument](./models/tool_definitions.py). Tools don't have to have arguments but the arguments list has to be declared. If the tool you're creating doesn't have inputs, define arguments as `arguments=[]`
#### Create Each Tool
- The tools themselves are defined in their own files in `/tools` - you can add a subfolder to organize them, see the hr tools for an example.
@@ -53,33 +61,33 @@ description="Help the user gather args for these tools in order: "
- The return dict should match the output format you specified in the goal's `example_conversation_history`
- tools are where the user input+model output becomes deterministic. Add validation here to make sure what the system is doing is valid and acceptable
-#### Add to `tools/__init__.py`
-- In `tools/__init__.py`, add an import statement for each new tool as well as an applicable return statement in `get_handler`. The tool name here should match the tool name as described in the goal's `description` field.
+#### Add to `tools/__init__.py` and the tool get_handler()
+- In [tools/__init__.py](./tools/__init__.py), add an import statement for each new tool as well as an applicable return statement in `get_handler`. The tool name here should match the tool name as described in the goal's `description` field.
Example:
```
if tool_name == "CurrentPTO":
return current_pto
```
-### Configuring the Starting Goal
+### Existing Travel Goals
The agent can be configured to pursue different goals using the `AGENT_GOAL` environment variable in your `.env` file.
#### Goal: Find an event in Australia / New Zealand, book flights to it and invoice the user for the cost
- `AGENT_GOAL=goal_event_flight_invoice` (default) - Helps users find events, book flights, and arrange train travel with invoice generation
- - This is the scenario in the video above
+ - This is the scenario in the [original video](https://www.youtube.com/watch?v=GEXllEH2XiQ)
#### Goal: Find a Premier League match, book train tickets to it and invoice the user for the cost
- `AGENT_GOAL=goal_match_train_invoice` - Focuses on Premier League match attendance with train booking and invoice generation
- - This is a new goal that is part of an upcoming conference talk
+ - This is a new goal that is part of the [Replay 2025 talk](https://www.youtube.com/watch?v=YDxAWrIBQNE).
-If not specified, the agent defaults to `goal_event_flight_invoice`. Each goal comes with its own set of tools and conversation flows designed for specific use cases. You can examine `tools/goal_registry.py` to see the detailed configuration of each goal.
+If not specified, the agent defaults to all goals. Each goal, including these, comes with its own set of tools and conversation flows designed for specific use cases. You can examine `tools/goal_registry.py` to see the detailed configuration of each goal.
-See the next section for tool configuration for each goal.
+See the next section for tool configuration for these goals.
-### Configuring Existing Tools
+#### Configuring Travel Goal Tools
-#### Agent Goal: goal_event_flight_invoice (default)
+##### Agent Goal: goal_event_flight_invoice (default)
* The agent uses a mock function to search for events. This has zero configuration.
* By default the agent uses a mock function to search for flights.
* If you want to use the real flights API, go to `tools/search_flights.py` and replace the `search_flights` function with `search_flights_real_api` that exists in the same file.
@@ -89,7 +97,7 @@ See the next section for tool configuration for each goal.
* It's free to sign up and get a key at [Stripe](https://stripe.com/)
* If you're lazy go to `tools/create_invoice.py` and replace the `create_invoice` function with the mock `create_invoice_example` that exists in the same file.
-#### Agent Goal: goal_match_train_invoice
+##### Agent Goal: goal_match_train_invoice
* Finding a match requires a key from [Football Data](https://www.football-data.org). Sign up for a free account, then see the 'My Account' page to get your API token. Set `FOOTBALL_DATA_API_KEY` to this value.
* If you're lazy go to `tools/search_fixtures.py` and replace the `search_fixtures` function with the mock `search_fixtures_example` that exists in the same file.
diff --git a/architecture-decisions.md b/architecture-decisions.md
new file mode 100644
index 0000000..7c146d1
--- /dev/null
+++ b/architecture-decisions.md
@@ -0,0 +1,33 @@
+# Architecture Decisions
+This documents some of the "why" behind the [architecture](./architecture.md).
+
+## AI Models
+We wanted to have flexibility to use different models, because this space is changing rapidly and models get better regularly.
+Also, for you, we wanted to let you pick your model of choice. The system is designed to make changing models out simple. For how to do that, checkout the [setup guide](./setup.md).
+
+## Temporal
+We asked one of the AI models used in this demo to answer this question (edited minorly):
+
+### Reliability and State Management:
+ Temporal ensures durability and fault tolerance, which are critical for agentic AI systems that involve long-running, complex workflows. For example, it preserves application state across failures, allowing AI agents to resume from where they left off without losing progress. Major AI companies use this for research experiments and agentic flows, where reliability is essential for continuous exploration.
+### Handling Complex, Dynamic Workflows:
+Agentic AI often involves unpredictable, multi-step processes like web crawling or data searching. Temporal’s workflow orchestration simplifies managing these tasks by abstracting complexity, providing features like retries, timeouts, and signals/queries. Temporal makes observability and resuming failed complex experiments and deep searches simple.
+### Scalability and Speed:
+Temporal enables rapid development and scaling, crucial for AI systems handling large-scale experiments or production workloads. AI model deployment and SRE teams use it to get code to production quickly with scale as a focus, while research teams can (and do!) run hundreds of experiments daily. Temporal customers report a significant reduction in development time (e.g., 20 weeks to 2 weeks for a feature).
+### Observability and Debugging:
+Agentic AI systems need insight into where processes succeed or fail. Temporal provides end-to-end visibility and durable workflow history, which Temporal customers are using to track agentic flows and understand failure points.
+### Simplified Error Handling:
+Temporal abstracts failure management (e.g., retries, rollbacks) so developers can focus on AI logic rather than "plumbing" code. This is vital for agentic AI, where external interactions (e.g., APIs, data sources) are prone to failure.
+### Flexibility for Experimentation:
+For research-heavy agentic AI, Temporal supports dynamic, code-first workflows and easy integration of new signals/queries, aligning with researchers needs to iterate quickly on experimental paths.
+
+In essence, Temporal’s value lies in its ability to make agentic AI systems more reliable, scalable, and easier to develop by handling the underlying complexity of distributed workflows for both research and applied AI tasks.
+
+Temporal was built to solve the problems of distributed computing, including scalability, reliability, security, visibility, and complexity. Agentic AI systems are complex distributed systems, so Temporal should fit well. Scaling, security, and productionalization are major pain points in March 2025 for building agentic systems.
+
+In this system Temporal lets you:
+- Orchestrate interactions across distributed data stores and tools
+- Hold state, potentially over long periods of time
+- Ability to ‘self-heal’ and retry until the (probabilistic) LLM returns valid data
+- Support for human intervention such as approvals
+- Parallel processing for efficiency of data retrieval and tool use
\ No newline at end of file
diff --git a/setup.md b/setup.md
index 5f20618..1afa4c1 100644
--- a/setup.md
+++ b/setup.md
@@ -1,4 +1,5 @@
-## Configuration
+# Setup Guide
+## Initial Configuration
This application uses `.env` files for configuration. Copy the [.env.example](.env.example) file to `.env` and update the values:
@@ -6,6 +7,12 @@ This application uses `.env` files for configuration. Copy the [.env.example](.e
cp .env.example .env
```
+Then add API keys, configuration, as desired.
+If you want to show confirmations/enable the debugging UI, set
+```bash
+SHOW_CONFIRM=True
+```
+
### Agent Goal Configuration
The agent can be configured to pursue different goals using the `AGENT_GOAL` environment variable in your `.env` file.
@@ -173,4 +180,6 @@ If you're running your train API above on a different host/port then change the
- `tool_registry.py` contains the mapping of tool names to tool definitions (so the AI understands how to use them)
- `goal_registry.py` contains descriptions of goals and the tools used to achieve them
- The tools themselves are defined in their own files in `/tools`
-- Note the mapping in `tools/__init__.py` to each tool
\ No newline at end of file
+- Note the mapping in `tools/__init__.py` to each tool
+
+For more details, check out [adding goals and tools guide](./adding-goals-and-tools.md).
\ No newline at end of file
diff --git a/todo.md b/todo.md
index f0f7596..44653c0 100644
--- a/todo.md
+++ b/todo.md
@@ -1,34 +1,32 @@
# todo list
-[ ] add confirmation env setting to setup guide
+[x] add confirmation env setting to setup guide
-[ ] how to add more scenarios, tools
+[ ] try claude-3-7-sonnet-20250219, see [tool_activities.py](./activities/tool_activities.py)
+[ ] make agent respond to name of goals and not just numbers
+[x] L look at slides
+[ ] josh to do fintech scenarios
+[ ] expand [tests](./tests/agent_goal_workflow_test.py)
+[x] fix logging statements not to be all warn, maybe set logging level to info
-[ ] create tests
-[ ] fix logging statements not to be all warn, maybe set logging level to info
+[x] create people management scenarios
-[ ] create people management scenarios
+[ ] 2. Others HR goals:
+- book work travel
+- check insurance coverages
+- expense management
+- check in on the health of the team
-[ ] 2. Others:
--- check pay status
--- book work travel
--- check insurance coverages
--- expense management
--- check in on the health of the team
--- check pto
+[ ] fintech goals
+- Fraud Detection and Prevention - The AI monitors transactions across accounts, flagging suspicious activities (e.g., unusual spending patterns or login attempts) and autonomously freezing accounts or notifying customers and compliance teams.
+- Personalized Financial Advice - An AI agent analyzes a customer’s financial data (e.g., income, spending habits, savings, investments) and provides tailored advice, such as budgeting tips, investment options, or debt repayment strategies.
+- Portfolio Management and Rebalancing - The AI monitors a customer’s investment portfolio, rebalancing it automatically based on market trends, risk tolerance, and financial goals (e.g., shifting assets between stocks, bonds, or crypto).
+- money movement - start money transfer
+- [x] account balance -
-[x] demo the reasons why:
-- Orchestrate interactions across distributed data stores and tools
-- Hold state, potentially over long periods of time
-- Ability to ‘self-heal’ and retry until the (probabilistic) LLM returns valid data
-- Support for human intervention such as approvals
-- Parallel processing for efficiency of data retrieval and tool use
-[ ] ask the ai agent how it did at the end of the conversation, was it efficient? successful? insert a search attribute to document that before return
+[ ] ask the ai agent how it did at the end of the conversation, was it efficient? successful? insert a search attribute to document that before return
- Insight into the agent’s performance
-[x] customize prompts in [workflow to manage scenario](./workflows/tool_workflow.py)
-[x] add in new tools?
-
[ ] non-retry the api key error - "Invalid API Key provided: sk_test_**J..." and "AuthenticationError"
[ ] make it so you can yeet yourself out of a goal and pick a new one
diff --git a/tools/__init__.py b/tools/__init__.py
index c27b8c2..0dd10c0 100644
--- a/tools/__init__.py
+++ b/tools/__init__.py
@@ -11,6 +11,10 @@ from .transfer_control import transfer_control
from .hr.current_pto import current_pto
from .hr.book_pto import book_pto
from .hr.future_pto_calc import future_pto_calc
+from .hr.checkpaybankstatus import checkpaybankstatus
+
+from .fin.check_account_valid import check_account_valid
+from .fin.get_account_balances import get_account_balance
from .give_hint import give_hint
from .guess_location import guess_location
@@ -41,6 +45,12 @@ def get_handler(tool_name: str):
return book_pto
if tool_name == "FuturePTOCalc":
return future_pto_calc
+ if tool_name == "CheckPayBankStatus":
+ return checkpaybankstatus
+ if tool_name == "FinCheckAccountIsValid":
+ return check_account_valid
+ if tool_name == "FinCheckAccountBalance":
+ return get_account_balance
if tool_name == "GiveHint":
return give_hint
if tool_name == "GuessLocation":
diff --git a/tools/data/customer_account_data.json b/tools/data/customer_account_data.json
new file mode 100644
index 0000000..630c698
--- /dev/null
+++ b/tools/data/customer_account_data.json
@@ -0,0 +1,58 @@
+{
+ "accounts": [
+ {
+ "name": "Matt Murdock",
+ "email": "matt.murdock@nelsonmurdock.com",
+ "account_id": "11235",
+ "checking_balance": 875.40,
+ "savings_balance": 3200.15,
+ "bitcoin_balance": 0.1378,
+ "account_creation_date": "2014-03-10"
+ },
+ {
+ "name": "Foggy Nelson",
+ "email": "foggy.nelson@nelsonmurdock.com",
+ "account_id": "112358",
+ "checking_balance": 1523.67,
+ "savings_balance": 4875.90,
+ "bitcoin_balance": 0.0923,
+ "account_creation_date": "2014-03-10"
+ },
+ {
+ "name": "Karen Page",
+ "email": "karen.page@nelsonmurdock.com",
+ "account_id": "112",
+ "checking_balance": 645.25,
+ "savings_balance": 1830.50,
+ "bitcoin_balance": 0.0456,
+ "account_creation_date": "2015-01-15"
+ },
+ {
+ "name": "Wilson Fisk",
+ "email": "wilson.fisk@fiskcorp.com",
+ "account_id": "11",
+ "checking_balance": 25000.00,
+ "savings_balance": 150000.75,
+ "bitcoin_balance": 5987.6721,
+ "account_creation_date": "2013-09-20"
+ },
+ {
+ "name": "Frank Castle",
+ "email": "frank.castle@vigilante.net",
+ "account_id": "1",
+ "checking_balance": 320.10,
+ "savings_balance": 0.30,
+ "bitcoin_balance": 15.2189,
+ "account_creation_date": "2016-02-05"
+ },
+ {
+ "name": "Joshua Smith",
+ "email": "joshmsmith@gmail.com",
+ "account_id": "11235813",
+ "checking_balance": 3021.90,
+ "savings_balance": 500.50,
+ "bitcoin_balance": 0.001,
+ "account_creation_date": "2020-03-19"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tools/data/employee_pto_data.json b/tools/data/employee_pto_data.json
index 38a6329..c5c38d6 100644
--- a/tools/data/employee_pto_data.json
+++ b/tools/data/employee_pto_data.json
@@ -8,7 +8,7 @@
"hrsAddedPerMonth": 8
},
{
- "email": "lainecaseysmith@gmail.com",
+ "email": "laine@awesome.com",
"currentPTOHrs": 40,
"hrsAddedPerMonth": 12
}
diff --git a/tools/fin/check_account_valid.py b/tools/fin/check_account_valid.py
new file mode 100644
index 0000000..d339118
--- /dev/null
+++ b/tools/fin/check_account_valid.py
@@ -0,0 +1,24 @@
+from pathlib import Path
+import json
+
+# this is made to demonstrate functionality but it could just as durably be an API call
+# called as part of a temporal activity with automatic retries
+def check_account_valid(args: dict) -> dict:
+
+ email = args.get("email")
+ account_id = args.get("account_id")
+
+ file_path = Path(__file__).resolve().parent.parent / "data" / "customer_account_data.json"
+ if not file_path.exists():
+ return {"error": "Data file not found."}
+
+ with open(file_path, "r") as file:
+ data = json.load(file)
+ account_list = data["accounts"]
+
+ for account in account_list:
+ if account["email"] == email or account["account_id"] == account_id:
+ return{"status": "account valid"}
+
+ return_msg = "Account not found with email address " + email + " or account ID: " + account_id
+ return {"error": return_msg}
\ No newline at end of file
diff --git a/tools/fin/get_account_balances.py b/tools/fin/get_account_balances.py
new file mode 100644
index 0000000..ca44fb6
--- /dev/null
+++ b/tools/fin/get_account_balances.py
@@ -0,0 +1,24 @@
+from pathlib import Path
+import json
+
+# this is made to demonstrate functionality but it could just as durably be an API call
+# this assumes it's a valid account - use check_account_valid() to verify that first
+def get_account_balance(args: dict) -> dict:
+
+ account_key = args.get("accountkey")
+
+ file_path = Path(__file__).resolve().parent.parent / "data" / "customer_account_data.json"
+ if not file_path.exists():
+ return {"error": "Data file not found."}
+
+ with open(file_path, "r") as file:
+ data = json.load(file)
+ account_list = data["accounts"]
+
+ for account in account_list:
+ if account["email"] == account_key or account["account_id"] == account_key:
+ #return{"status": "account valid"}
+ return{ "name": account["name"], "email": account["email"], "account_id": account["account_id"], "checking_balance": account["checking_balance"], "savings_balance": account["savings_balance"], "bitcoin_balance": account["bitcoin_balance"], "account_creation_date": account["account_creation_date"] }
+
+ return_msg = "Account not found with email address " + email + " or account ID: " + account_id
+ return {"error": return_msg}
\ No newline at end of file
diff --git a/tools/give_hint.py b/tools/give_hint.py
index a8072ad..a2fad2f 100644
--- a/tools/give_hint.py
+++ b/tools/give_hint.py
@@ -8,17 +8,17 @@ TREASURE_LOCATION = {
}
HINTS = [
- "state of Washington",
- "city of Seattle",
+ "country of " + TREASURE_LOCATION["country"],
+ "state of " + TREASURE_LOCATION["state_full"],
+ "city of " + TREASURE_LOCATION["city"],
"at a company HQ",
+ "The company's tech traces its roots to a project called Cadence", #thanks, Grok
+ "The company offers a tool that lets developers write code as if it's running forever, no matter what crashes", #thanks, Grok
]
-''' Grok provided hints:
-Here are additional company-specific clues about Temporal that could help players in your game guess the address (300 Lenora St, Seattle, WA) by focusing on the company itself. These are designed to be intriguing and game-friendly:
-
+''' Additional Grok provided hints about Temporal:
"This company was founded by two engineers who previously worked on a system named after a South American river at Uber."
"Their platform is all about orchestrating workflows that can survive failures—like a conductor keeping the music going."
"They offer a tool that lets developers write code as if it’s running forever, no matter what crashes."
-"The company’s tech traces its roots to a project called Cadence, which they took to the next level."
"Their mission is tied to making distributed systems feel as simple as writing a single app."
"They’ve got a knack for ‘durability’—both in their software and their growing reputation."
"This outfit spun out of experiences at AWS and Uber, blending cloud and ride-sharing know-how."
@@ -34,7 +34,6 @@ def give_hint(args: dict) -> dict:
index = hint_total % len(HINTS)
hint_text = HINTS[index]
- print(f"hint_total: {hint_total}, length: {len(HINTS)}, index: {index}")
hint_total = hint_total + 1
return {
"hint_number": hint_total,
diff --git a/tools/goal_registry.py b/tools/goal_registry.py
index 67b5cc0..343bb32 100644
--- a/tools/goal_registry.py
+++ b/tools/goal_registry.py
@@ -222,6 +222,93 @@ goal_hr_schedule_pto = AgentGoal(
),
)
+# This goal uses the data/employee_pto_data.json file as dummy data.
+goal_hr_check_pto = AgentGoal(
+ id = "goal_hr_check_pto",
+ category_tag="hr",
+ agent_name="Check PTO Amount",
+ agent_friendly_description="Check your available PTO.",
+ tools=[
+ tool_registry.current_pto_tool,
+ tool_registry.list_agents_tool, #last tool must be list_agents to fasciliate changing back to picking an agent again at the end
+ ],
+ description="The user wants to check their paid time off (PTO) after today's date. To assist with that goal, help the user gather args for these tools in order: "
+ "1. CurrentPTO: Tell the user how much PTO they currently have ",
+ starter_prompt=starter_prompt_generic,
+ example_conversation_history="\n ".join(
+ [
+ "user: I'd like to check my time off amounts at the current time",
+ "agent: Sure! I can help you out with that. May I have your email address?",
+ "user: bob.johnson@emailzzz.com",
+ "agent: Great! I can tell you how much PTO you currently have accrued.",
+ "user_confirmed_tool_run: ",
+ "tool_result: { 'num_hours': 400, 'num_days': 50 }",
+ "agent: You have 400 hours, or 50 days, of PTO available.",
+ ]
+ ),
+)
+
+# check integration with bank
+goal_hr_check_paycheck_bank_integration_status = AgentGoal(
+ id = "goal_hr_check_paycheck_bank_integration_status",
+ category_tag="hr",
+ agent_name="Check paycheck bank integration status",
+ agent_friendly_description="Check your integration between paycheck payer and your financial institution.",
+ tools=[
+ tool_registry.paycheck_bank_integration_status_check,
+ tool_registry.list_agents_tool, #last tool must be list_agents to fasciliate changing back to picking an agent again at the end
+ ],
+ description="The user wants to check their bank integration used to deposit their paycheck. To assist with that goal, help the user gather args for these tools in order: "
+ "1. CheckPayBankStatus: Tell the user the status of their paycheck bank integration ",
+ starter_prompt=starter_prompt_generic,
+ example_conversation_history="\n ".join(
+ [
+ "user: I'd like to check paycheck bank integration",
+ "agent: Sure! I can help you out with that. May I have your email address?",
+ "user: bob.johnson@emailzzz.com",
+ "agent: Great! I can tell you what the status is for your paycheck bank integration.",
+ "user_confirmed_tool_run: ",
+ "tool_result: { 'status': connected }",
+ "agent: Your paycheck bank deposit integration is properly connected.",
+ ]
+ ),
+)
+
+# this tool checks account balances, and uses ./data/customer_account_data.json as dummy data
+goal_fin_check_account_balances = AgentGoal(
+ id = "goal_fin_check_account_balances",
+ category_tag="fin",
+ agent_name="Check balances",
+ agent_friendly_description="Check your account balances in Checking, Savings, etc.",
+ tools=[
+ tool_registry.financial_check_account_is_valid,
+ tool_registry.financial_get_account_balances,
+ tool_registry.list_agents_tool, #last tool must be list_agents to fasciliate changing back to picking an agent again at the end
+ ],
+ description="The user wants to check their account balances at the bank or financial institution. To assist with that goal, help the user gather args for these tools in order: "
+ "1. FinCheckAccountIsValid: validate the user's account is valid"
+ "2. FinCheckAccountBalance: Tell the user their account balance at the bank or financial institution",
+ starter_prompt=starter_prompt_generic,
+ example_conversation_history="\n ".join(
+ [
+ "user: I'd like to check my account balances",
+ "agent: Sure! I can help you out with that. May I have your email address or account number?",
+ "user: email is bob.johnson@emailzzz.com ",
+ "user_confirmed_tool_run: ",
+ "tool_result: { 'status': account valid }",
+ "agent: Great! I can tell you what the your account balances are.",
+ "user_confirmed_tool_run: ",
+ "tool_result: { 'name': Matt Murdock, 'email': matt.murdock@nelsonmurdock.com, 'account_id': 11235, 'checking_balance': 875.40, 'savings_balance': 3200.15, 'bitcoin_balance': 0.1378, 'account_creation_date': 2014-03-10 }",
+ "agent: Your account balances are as follows: \n "
+ "Checking: $875.40. \n "
+ "Savings: $3200.15. \n "
+ "Bitcoint: 0.1378 \n "
+ "Thanks for being a customer since 2014!",
+ ]
+ ),
+)
+
+#todo add money movement, fraud check (update with start)
#Add the goals to a list for more generic processing, like listing available agents
goal_list: List[AgentGoal] = []
goal_list.append(goal_choose_agent_type)
@@ -229,3 +316,8 @@ goal_list.append(goal_pirate_treasure)
goal_list.append(goal_event_flight_invoice)
goal_list.append(goal_match_train_invoice)
goal_list.append(goal_hr_schedule_pto)
+goal_list.append(goal_hr_check_pto)
+goal_list.append(goal_hr_check_paycheck_bank_integration_status)
+goal_list.append(goal_fin_check_account_balances)
+
+
diff --git a/tools/hr/checkpaybankstatus.py b/tools/hr/checkpaybankstatus.py
new file mode 100644
index 0000000..0f98e71
--- /dev/null
+++ b/tools/hr/checkpaybankstatus.py
@@ -0,0 +1,15 @@
+from pathlib import Path
+import json
+
+
+def checkpaybankstatus(args: dict) -> dict:
+
+ email = args.get("email")
+
+ if email == "grinch@grinch.com":
+ print("THE GRINCH IS FOUND!")
+ return {"status": "no money for the grinch"}
+
+ # could do logic here or look up data but for now everyone but the grinch is getting paid
+ return_msg = "connected"
+ return {"status": return_msg}
\ No newline at end of file
diff --git a/tools/tool_registry.py b/tools/tool_registry.py
index 74ecd1a..3930cc6 100644
--- a/tools/tool_registry.py
+++ b/tools/tool_registry.py
@@ -50,6 +50,7 @@ guess_location_tool = ToolDefinition(
),
],
)
+
# ----- Travel use cases tools -----
search_flights_tool = ToolDefinition(
name="SearchFlights",
@@ -198,12 +199,12 @@ future_pto_calc_tool = ToolDefinition(
ToolArgument(
name="start_date",
type="string",
- description="Start date of proposed PTO",
+ description="Start date of proposed PTO, sent in the form yyyy-mm-dd",
),
ToolArgument(
name="end_date",
type="string",
- description="End date of proposed PTO",
+ description="End date of proposed PTO, sent in the form yyyy-mm-dd",
),
ToolArgument(
name="email",
@@ -221,12 +222,12 @@ book_pto_tool = ToolDefinition(
ToolArgument(
name="start_date",
type="string",
- description="Start date of proposed PTO",
+ description="Start date of proposed PTO, sent in the form yyyy-mm-dd",
),
ToolArgument(
name="end_date",
type="string",
- description="End date of proposed PTO",
+ description="End date of proposed PTO, sent in the form yyyy-mm-dd",
),
ToolArgument(
name="email",
@@ -239,4 +240,49 @@ book_pto_tool = ToolDefinition(
description="Indication of user's desire to book PTO",
),
],
+)
+
+paycheck_bank_integration_status_check = ToolDefinition(
+ name="CheckPayBankStatus",
+ description="Check status of Bank Integration for Paychecks. "
+ "Returns the status of the bank integration, connected or disconnected. ",
+ arguments=[
+ ToolArgument(
+ name="email",
+ type="string",
+ description="email address of user",
+ ),
+ ],
+)
+
+financial_check_account_is_valid = ToolDefinition(
+ name="FinCheckAccountIsValid",
+ description="Check if an account is valid by email address or account ID. "
+ "Returns the account status, valid or invalid. ",
+ arguments=[
+ ToolArgument(
+ name="email",
+ type="string",
+ description="email address of user",
+ ),
+ ToolArgument(
+ name="account_id",
+ type="string",
+ description="account ID of user",
+ ),
+ ],
+)
+
+financial_get_account_balances = ToolDefinition(
+ name="FinCheckAccountBalance",
+ description="Get account balance for your accounts. "
+ "Returns the account balances of your accounts. ",
+
+ arguments=[
+ ToolArgument(
+ name="accountkey",
+ type="string",
+ description="email address or account ID of user",
+ ),
+ ],
)
\ No newline at end of file
diff --git a/workflows/agent_goal_workflow.py b/workflows/agent_goal_workflow.py
index d52e9ab..86324ff 100644
--- a/workflows/agent_goal_workflow.py
+++ b/workflows/agent_goal_workflow.py
@@ -26,11 +26,11 @@ with workflow.unsafe.imports_passed_through():
# Constants
MAX_TURNS_BEFORE_CONTINUE = 250
-SHOW_CONFIRM = True
show_confirm_env = os.getenv("SHOW_CONFIRM")
-if show_confirm_env is not None:
- if show_confirm_env == "False":
- SHOW_CONFIRM = False
+if show_confirm_env is not None and show_confirm_env.lower() == "false":
+ SHOW_CONFIRM = False
+else:
+ SHOW_CONFIRM = True
#ToolData as part of the workflow is what's accessible to the UI - see LLMResponse.jsx for example
class ToolData(TypedDict, total=False):
@@ -259,9 +259,10 @@ class AgentGoalWorkflow:
for listed_goal in goal_list:
if listed_goal.id == goal:
self.goal = listed_goal
- # self.goal = goals.get(goal)
workflow.logger.info("Changed goal to " + goal)
- #todo reset goal or tools if this doesn't work or whatever
+ if goal is None:
+ workflow.logger.warning("Goal not set after goal reset, probably bad.") # if this happens, there's probably a problem with the goal list
+
# workflow function that defines if chat should end
def chat_should_end(self) -> bool: