-
Notifications
You must be signed in to change notification settings - Fork 13
tests: added integration tests #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
name: Integration testing | ||
|
||
on: | ||
push: | ||
branches: [ main, develop ] | ||
pull_request: | ||
branches: [ main ] | ||
|
||
jobs: | ||
integration-tests: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: read | ||
pull-requests: write | ||
|
||
strategy: | ||
matrix: | ||
include: | ||
- build-dir: company-research-agent | ||
context: ./testcases/company-research-agent | ||
agent-input: '{"company_name":"uipath"}' | ||
- build-dir: simple-local-mcp | ||
context: ./testcases/simple-local-mcp | ||
agent-input: '{"messages": [{"type": "human", "content": "What is 2+2"}]}' | ||
- build-dir: ticket-classification | ||
context: ./testcases/ticket-classification | ||
agent-input: '{"message": "GET Assets API does not enforce proper permissions Assets.View", "ticket_id": "TICKET-2345"}' | ||
has-human-loop: "true" | ||
- build-dir: multi-agent-supervisor-researcher-coder | ||
context: ./testcases/multi-agent-supervisor-researcher-coder | ||
agent-input: '{"question": "First, please state the Pythagorean theorem. Give only the formula, using variables a, b, and c. Then apply this formula to calculate the value when a=2 and b=3."}' | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
|
||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v3 | ||
|
||
|
||
- name: Build Docker image (${{ matrix.build-dir }}) | ||
run: | | ||
docker build -f Dockerfile \ | ||
-t ${{ matrix.build-dir }}:test \ | ||
--build-arg CLIENT_ID="${{ secrets.ALPHA_TEST_CLIENT_ID }}" \ | ||
--build-arg CLIENT_SECRET="${{ secrets.ALPHA_TEST_CLIENT_SECRET }}" \ | ||
--build-arg BASE_URL="${{ secrets.ALPHA_BASE_URL }}" \ | ||
--build-arg AGENT_INPUT='${{ matrix.agent-input }}' \ | ||
${{ matrix.has-human-loop == 'true' && '--build-arg SKIP_HUMAN_APPROVAL=false --build-arg USE_REGULAR_INTERRUPT=true' || '' }} \ | ||
${{ matrix.context }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
FROM ghcr.io/astral-sh/uv:python3.12-bookworm | ||
|
||
WORKDIR /app | ||
|
||
COPY . . | ||
|
||
RUN uv sync | ||
|
||
ARG CLIENT_ID | ||
ARG CLIENT_SECRET | ||
ARG BASE_URL | ||
ARG AGENT_INPUT | ||
ARG SKIP_HUMAN_APPROVAL=false | ||
ARG USE_REGULAR_INTERRUPT=false | ||
|
||
# Validate required environment variables | ||
RUN if [ -z "$CLIENT_ID" ]; then echo "CLIENT_ID build arg is required" && exit 1; fi | ||
RUN if [ -z "$CLIENT_SECRET" ]; then echo "CLIENT_SECRET build arg is required" && exit 1; fi | ||
RUN if [ -z "$BASE_URL" ]; then echo "BASE_URL build arg is required" && exit 1; fi | ||
RUN if [ -z "$AGENT_INPUT" ]; then echo "AGENT_INPUT build arg is required" && exit 1; fi | ||
|
||
# Set environment variables for runtime | ||
ENV CLIENT_ID=$CLIENT_ID | ||
ENV CLIENT_SECRET=$CLIENT_SECRET | ||
ENV BASE_URL=$BASE_URL | ||
ENV TAVILY_API_KEY=${TAVILY_API_KEY:-""} | ||
ENV UIPATH_TENANT_ID=${UIPATH_TENANT_ID:-""} | ||
|
||
# Human-in-the-loop settings (only for agents that support it) | ||
ENV SKIP_HUMAN_APPROVAL=${SKIP_HUMAN_APPROVAL:-"false"} | ||
ENV USE_REGULAR_INTERRUPT=${USE_REGULAR_INTERRUPT:-"false"} | ||
|
||
# Authenticate with UiPath during build | ||
RUN uv run uipath auth --client-id="$CLIENT_ID" --client-secret="$CLIENT_SECRET" --base-url="$BASE_URL" | ||
|
||
RUN uv run uipath pack | ||
|
||
RUN uv run uipath run agent "$AGENT_INPUT" | ||
|
||
# Only run resume if both conditions are met: | ||
# 1. USE_REGULAR_INTERRUPT is explicitly set to true (agent supports interrupts) | ||
# 2. SKIP_HUMAN_APPROVAL is false (interrupt will actually happen) | ||
RUN if [ "${USE_REGULAR_INTERRUPT:-false}" = "true" ] && [ "${SKIP_HUMAN_APPROVAL:-false}" = "false" ]; then \ | ||
echo "Running resume for agent with regular interrupt..."; \ | ||
uv run uipath run agent '{"Answer": true}' --resume; \ | ||
else \ | ||
echo "Skipping resume - no interrupt expected or not supported"; \ | ||
fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Project Samples | ||
|
||
## [Multi agent supervisor, researcher, coder](multi-agent-supervisor-researcher-coder) | ||
This sample showcases a multi-agent system, involving a supervisor, a researcher, and a coder working in coordination to tackle complex tasks. | ||
|
||
## [Multi agent planner, researcher, coder distributed](multi-agent-planner-researcher-coder-distributed) | ||
Here, a multi-agent system breaks down complex tasks into discreet steps, routing them to specialized agents. Each agent operates **independently** and can be deployed as a separate process. The system includes a planner, researcher, and coder agent. | ||
|
||
## [RAG-quiz-generator](RAG-quiz-generator) | ||
The RAG Sample project demonstrates the implementation of a Retrieval-Augmented Generation (RAG) system using [UiPath Context Grounding](https://docs.uipath.com/automation-cloud/automation-cloud/latest/admin-guide/about-context-grounding). | ||
|
||
## [Retrieval chain](retrieval-chain) | ||
This example shows how to retrieve relevant documents for a query, using the UiPath Context Grounding vectorstore. It also integrates this into a Langchain retrieval chain for response formulation. | ||
|
||
## [Simple local MCP](simple-local-mcp) | ||
This sample shows how to create an agent using LangGraph with multiple tool servers via the MCP (Model Context Protocol) standard. | ||
|
||
## [Simple remote MCP](simple-remote-mcp) | ||
This sample demonstrates the creation of an agent using LangGraph, which connects to a remote MCP (Model Context Protocol) Server. | ||
|
||
## [Ticket classification](ticket-classification) | ||
This sample demonstrates automatic classification of support tickets into categories. It includes a human approval step via UiPath Action Center. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
UIPATH_URL=https://alpha.uipath.com/<organization>/<tenant> | ||
UIPATH_ACCESS_TOKEN=YOUR TOKEN HERE | ||
UIPATH_TENANT_ID=YOUR_TENANT_ID | ||
UIPATH_ORGANIZATION_ID=YOUR_ORGANIZATION_ID | ||
TAVILY_API_KEY=your_tavily_api_key |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
--- | ||
config: | ||
flowchart: | ||
curve: linear | ||
--- | ||
graph TD; | ||
__start__([<p>__start__</p>]):::first | ||
__end__([<p>__end__</p>]):::last | ||
__start__ --> researcher___start__; | ||
researcher___end__ --> __end__; | ||
subgraph researcher | ||
researcher___start__(<p>__start__</p>) | ||
researcher_agent(agent) | ||
researcher_tools(tools) | ||
researcher___end__(<p>__end__</p>) | ||
researcher___start__ --> researcher_agent; | ||
researcher_tools --> researcher_agent; | ||
researcher_agent -.-> researcher_tools; | ||
researcher_agent -.-> researcher___end__; | ||
end | ||
classDef default fill:#f2f0ff,line-height:1.2 | ||
classDef first fill-opacity:0 | ||
classDef last fill:#bfb6fc |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import os | ||
from typing import Union | ||
|
||
from langchain_community.tools import DuckDuckGoSearchResults | ||
from langchain_community.tools.tavily_search import TavilySearchResults | ||
from langgraph.graph import END, START, MessagesState, StateGraph | ||
from langgraph.prebuilt import create_react_agent | ||
from pydantic import BaseModel | ||
|
||
from uipath_langchain.chat import UiPathAzureChatOpenAI | ||
|
||
# Configuration constants | ||
MAX_SEARCH_RESULTS = 5 | ||
DEFAULT_MODEL = "gpt-4o-2024-08-06" | ||
ALTERNATIVE_MODEL = "claude-3-5-sonnet-latest" | ||
|
||
|
||
def get_search_tool() -> Union[TavilySearchResults, DuckDuckGoSearchResults]: | ||
"""Get the appropriate search tool based on available API keys.""" | ||
if os.getenv("TAVILY_API_KEY"): | ||
return TavilySearchResults(max_results=MAX_SEARCH_RESULTS) | ||
return DuckDuckGoSearchResults() | ||
|
||
|
||
# System prompt for the research agent | ||
SYSTEM_PROMPT = """You are an advanced AI assistant specializing in corporate research and outreach strategy development. Your primary functions are: | ||
1. Researching target companies: Gather comprehensive information about the specified company, including its history, industry position, products/services, and recent news. | ||
2. Analyzing organizational structures: Investigate and outline the company's internal structure, departments, and hierarchy. | ||
3. Identifying key decision-makers: Find and provide information on important executives and leaders within the company who are likely to be involved in decision-making processes. | ||
4. Developing outreach strategies: Based on the gathered information, create tailored strategies for effective communication and engagement with the company and its key personnel. | ||
|
||
To accomplish these tasks, follow these steps: | ||
1. Use the TavilySearchResults tool to find recent and relevant information about the company. | ||
2. Analyze the collected data to form insights about the company's structure, key decision-makers, and potential outreach strategies. | ||
|
||
When using the search tool: | ||
- Clearly state the purpose of each search. | ||
- Formulate effective search queries to find specific information about different aspects of the company. | ||
- If a search doesn't provide the expected information, try refining your query. | ||
|
||
When responding, structure your output as a comprehensive analysis. Use clear section headers to organize the information. Provide concise, actionable insights. If you need more information to complete any part of your analysis, clearly state what additional details would be helpful. | ||
|
||
Always maintain a professional and objective tone in your research and recommendations. Your goal is to provide accurate, valuable information that can be used to inform business decisions and outreach efforts. | ||
|
||
DO NOT do any math as specified in your instructions. | ||
""" | ||
|
||
|
||
def create_llm() -> UiPathAzureChatOpenAI: | ||
"""Create and configure the language model.""" | ||
return UiPathAzureChatOpenAI(model=DEFAULT_MODEL) | ||
# Alternative model option: | ||
# return ChatAnthropic(model=ALTERNATIVE_MODEL) | ||
|
||
|
||
def create_research_agent(): | ||
"""Create the research agent with configured LLM and tools.""" | ||
llm = create_llm() | ||
search_tool = get_search_tool() | ||
return create_react_agent(llm, tools=[search_tool], prompt=SYSTEM_PROMPT) | ||
|
||
|
||
class GraphState(BaseModel): | ||
"""State model for the research graph.""" | ||
company_name: str | ||
|
||
|
||
class GraphOutput(BaseModel): | ||
"""Output model for the research graph.""" | ||
response: str | ||
|
||
|
||
def create_user_message(company_name: str) -> str: | ||
"""Create a formatted user message for company research.""" | ||
return f"""Please provide a comprehensive analysis and outreach strategy for the company: {company_name}. Use the TavilySearchResults tool to gather information. Include detailed research on the company's background, organizational structure, key decision-makers, and a tailored outreach strategy. Format your response using the following section headers: | ||
|
||
1. Company Overview | ||
2. Organizational Structure | ||
3. Key Decision-Makers | ||
4. Outreach Strategy | ||
5. Additional Information Needed (if applicable) | ||
|
||
Ensure that each section is clearly labeled and contains relevant, concise information. If you need any additional specific information about {company_name} or its industry to enhance your analysis, please include your questions in the 'Additional Information Needed' section. | ||
""" | ||
|
||
|
||
async def research_node(state: GraphState) -> GraphOutput: | ||
"""Research node that performs company analysis.""" | ||
research_agent = create_research_agent() | ||
user_message = create_user_message(state.company_name) | ||
|
||
# Create message state for the agent | ||
message_state = MessagesState(messages=[{"role": "user", "content": user_message}]) | ||
|
||
# Invoke the research agent | ||
result = await research_agent.ainvoke(message_state) | ||
|
||
return GraphOutput(response=result["messages"][-1].content) | ||
|
||
|
||
def build_research_graph() -> StateGraph: | ||
"""Build and compile the research graph.""" | ||
builder = StateGraph(GraphState, output=GraphOutput) | ||
|
||
# Add nodes | ||
builder.add_node("researcher", research_node) | ||
|
||
# Add edges | ||
builder.add_edge(START, "researcher") | ||
builder.add_edge("researcher", END) | ||
|
||
return builder.compile() | ||
|
||
|
||
# Create the compiled graph | ||
graph = build_research_graph() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"dependencies": ["."], | ||
"graphs": { | ||
"agent": "./graph.py:graph" | ||
}, | ||
"env": ".env" | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
[project] | ||
name = "company-research-agent" | ||
version = "0.0.1" | ||
description = "Company research agent with Tavily web search" | ||
authors = [{ name = "John Doe", email = "[email protected]" }] | ||
|
||
requires-python = ">=3.10" | ||
dependencies = [ | ||
"langgraph>=0.2.55", | ||
"langchain-anthropic>=0.3.8", | ||
"tavily-python>=0.5.0", | ||
"uipath>=2.0.79", | ||
"uipath-langchain>=0.0.117", | ||
"duckduckgo-search>=8.1.1", | ||
"langchain-community>=0.3.21", | ||
"debugpy>=1.8.15", | ||
] | ||
|
||
[project.optional-dependencies] | ||
dev = ["mypy>=1.11.1", "ruff>=0.6.1"] | ||
|
||
[build-system] | ||
requires = ["setuptools>=73.0.0", "wheel"] | ||
build-backend = "setuptools.build_meta" | ||
|
||
[tool.setuptools.package-data] | ||
"*" = ["py.typed"] | ||
|
||
[tool.ruff] | ||
lint.select = [ | ||
"E", # pycodestyle | ||
"F", # pyflakes | ||
"I", # isort | ||
"D", # pydocstyle | ||
"D401", # First line should be in imperative mood | ||
"T201", | ||
"UP", | ||
] | ||
lint.ignore = [ | ||
"UP006", | ||
"UP007", | ||
"UP035", | ||
"D417", | ||
"E501", | ||
] | ||
|
||
[tool.ruff.lint.per-file-ignores] | ||
"tests/*" = ["D", "UP"] | ||
|
||
[[tool.uv.index]] | ||
name = "testpypi" | ||
url = "https://test.pypi.org/simple/" | ||
publish-url = "https://test.pypi.org/legacy/" | ||
explicit = true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"entryPoints": [ | ||
{ | ||
"filePath": "agent", | ||
"uniqueId": "0bf221a3-6cf6-4b81-bce3-d0ce260521f2", | ||
"type": "agent", | ||
"input": { | ||
"type": "object", | ||
"properties": { | ||
"company_name": { | ||
"title": "Company Name", | ||
"type": "string" | ||
} | ||
}, | ||
"required": [ | ||
"company_name" | ||
] | ||
}, | ||
"output": { | ||
"type": "object", | ||
"properties": { | ||
"response": { | ||
"title": "Response", | ||
"type": "string" | ||
} | ||
}, | ||
"required": [ | ||
"response" | ||
] | ||
} | ||
} | ||
], | ||
"bindings": { | ||
"version": "2.0", | ||
"resources": [] | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.