Share at:
Let’s be honest—company policies matter, and they’re not going anywhere.
But the reality is that common questions like “What’s the standard laptop I can have?”, “How do I expense $10 of API calls?”, or “Does this type of software use comply with company rules?” often feel complex, frustrating, and time-consuming—creating friction rather than flow.
A dedicated, contextualized, secured agent such that employees can ask and act on the company policy can fix that. Let’s how that experience would look like and how one can implement it within UiPath.
UiPath MCP server + LangChain ask and act on company policy via chat agent
This one is super simple, and it almost feels like a shame not to implement it. As in a recipe, the main ingredients you need are:
Your company policy text file
LangChain company policy agent
UiPath MCP Server
Claude Desktop (or similar)
(Optional) API Workflow for sending e-mails
Let’s take it step by step.
Write the company policies you want the Agent to be aware of and save them in a plain txt file (e.g., company_policy.txt). Fictional policy extract below:
Paid Time Off (PTO): • PTO requests for less than 5 days require at least 1 day advance notice. • PTO requests for 5 days or more require at least 5 days advance notice. • Employees are encouraged to plan their PTO in advance to ensure adequate coverage and minimal disruption to team operations. • All PTO requests must be submitted via email to the employee’s manager • For absences of 5 days or more, the PTO request email must also include: • A designated point of contact or persona who will take ownership of key responsibilities or hand off critical work during the employee’s absence.
In your UiPath platform account, in Orchestrator create a new Storage Bucket and upload the company_policy.txt file to it
With this, one can create a context grounding index based on the company_policy.txtby using Storage Bucket as data source.
The Coded Agent is built with the LangGraph framework and has a single node called policythat based on the user ask and company policy composes response via an LLM call
# Build the state graph builder = StateGraph(GraphInput, output=GraphOutput) builder.add_node("policy", policy_node) builder.add_edge(START, "policy") builder.add_edge("policy", END)
# Compile the graph graph = builder.compile()
Specifically, it:
Ingests the company policy context via a UiPath SDK ContextGroundingRetrievercall (getcontextdata_async in Annexes)
async def policy_node(state: GraphInput) -> GraphOutput: retriever = ContextGroundingRetriever( index_name="company-policy-index", number_of_results=100, ) try: context_data= await get_context_data_async(retriever, state.question) except IndexNotFound: context_data = system_prompt
And feeds the systemprompt, userquestion and companypolicycontextto an LLM call.
llm = UiPathAzureChatOpenAI(model="gpt-4o-2024-08-06")
system_prompt = """You are an advanced AI assistant specializing in answering questions about <> internal company policies...."""
### messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": state.question}, {"role":"user", "content": context_data[0].page_content}] ### result = await llm.ainvoke(messages)
After building the Coded Agents one should:
Add a Process in Orchestrator and set the environment configuration
Build a UiPath MCP Server directly in the UiPath platform by adding the company-policy agent as a tool and specifying a proper agent description. Once the UiPath MCP Server is built, copy the URL to be configured with the Claude Desktop app.
To grant secured access to the company policy one can configure Claude Desktop app to point to the UiPath MCP Server that exposes the companypolicyagent as a tool.
To generate a Personal Access Token (PAT) In UiPath Orchestrator go to User → Preferences → Personal Access Token.
Set the Name and Expiration date and add as scope the Orchestrator API Access (All).
Copy the PAT it will be used to configure Claude Desktop app.
If not already available, download and install the Claude Desktop app. In the app Settings go to Developer-> Edit Config.
This will open the claudedesktopconfig.jsonwhere the list of MCP Servers is defined. Example:
"CompanyPolicy": { "command": "npx", "args": [ "-y", "mcp-remote", "https:< UiPath MCP Server URL>", "--header", "Authorization:${AUTH_HEADER}" ], "env": { "AUTH_HEADER": "Bearer <YOUR Personal Access Token>" } }
Restart Claude Desktop to load the MCP configuration. The tools exposed by the MCP Server should be available and used whenever a related prompt like “I need to buy 10$ worth of API calls from OpenAI, what should I do per my company policy?“ is given.
Coded agent source code:
from langchain_anthropic import ChatAnthropic from langgraph.graph import END, START, MessagesState, StateGraph from langgraph.prebuilt import create_react_agent from pydantic import BaseModel from uipath_langchain.retrievers import ContextGroundingRetriever from langchain_core.documents import Document from uipath.models import InvokeProcess, IngestionInProgressException import httpx from uipath_langchain.chat.models import UiPathAzureChatOpenAI from langchain_openai import ChatOpenAI
class IndexNotFound(Exception): pass
# Define system prompt for company policy agent system_prompt = """You are an advanced AI assistant specializing in answering questions about <> internal company policies... """
llm = ChatOpenAI( model="gpt-4o", temperature=0, max_tokens=4000, timeout=30, max_retries=2, )
class GraphInput(BaseModel): """Input for the company policy agent graph.""" question: str
class GraphOutput(BaseModel): """Output for the company policy agent graph.""" response: str
async def get_context_data_async(retriever: ContextGroundingRetriever, question: str) -> list[Document]: no_of_retries = 5 context_data = None data_queried = False while no_of_retries != 0: try: context_data = await retriever.ainvoke(question) data_queried = True break except IngestionInProgressException as ex: logger.info(ex.message) no_of_retries -= 1 logger.info(f"{no_of_retries} retries left") time.sleep(5) except httpx.HTTPStatusError as err: if err.response.status_code == 404: raise IndexNotFound raise if not data_queried: raise Exception("Ingestion is taking too long.") return context_data
async def policy_node(state: GraphInput) -> GraphOutput: retriever = ContextGroundingRetriever( index_name="company-policy-index", number_of_results=100, ) try: context_data= await get_context_data_async(retriever, state.question) except IndexNotFound: context_data = system_prompt
messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": state.question}, {"role":"user", "content": context_data[0].page_content} ]
"""Process a company policy question and return a structured answer.""" user_message = f"""Please answer the following company policy question. Use clear section headers for each relevant policy area (Procurement Policy, Equipment Acquisition, PTO Policy). If the question is outside these topics, politely state your scope.\n\nQuestion: {state.question}""" result = await llm.ainvoke(messages) return GraphOutput(response=result.content)
# Build the state graph builder = StateGraph(GraphInput, output=GraphOutput) builder.add_node("policy", policy_node) builder.add_edge(START, "policy") builder.add_edge("policy", END)
# Compile the graph graph = builder.compile()
Topics:
Coded AgentsPrincipal Product Manager, UiPath
Sign up today and we'll email you the newest articles every week.
Thank you for subscribing! Each week, we'll send the best automation blog posts straight to your inbox.