Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions samples/calculator-agent/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.10
Binary file added samples/calculator-agent/README.md
Binary file not shown.
18 changes: 18 additions & 0 deletions samples/calculator-agent/agent.mermaid
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
config:
flowchart:
curve: linear
---
graph TD;
__start__([<p>__start__</p>]):::first
validate(validate)
calculate(calculate)
output(output)
__end__([<p>__end__</p>]):::last
__start__ --> validate;
calculate --> output;
validate --> calculate;
output --> __end__;
classDef default fill:#f2f0ff,line-height:1.2
classDef first fill-opacity:0
classDef last fill:#bfb6fc
49 changes: 0 additions & 49 deletions samples/calculator-agent/graph.py

This file was deleted.

12 changes: 6 additions & 6 deletions samples/calculator-agent/langgraph.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"dependencies": ["."],
"graphs": {
"agent": "./graph.py:graph"
},
"env": ".env"
}
"dependencies": ["."],
"graphs": {
"agent": "./main.py:graph"
},
"env": ".env"
}
143 changes: 143 additions & 0 deletions samples/calculator-agent/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
"""
Calculator Coded Agent
Performs mathematical operations on two numbers with validation
"""

from langgraph.graph import START, StateGraph, END
from pydantic import BaseModel, Field, field_validator
from typing import Union


class Input(BaseModel):
"""Input schema for calculator agent"""
a: Union[int, float] = Field(..., description="First number")
b: Union[int, float] = Field(..., description="Second number")
operator: str = Field(..., description="Mathematical operator: +, -, *, /, **, %, //")

@field_validator('a', 'b')
@classmethod
def validate_number(cls, v):
"""Ensure inputs are valid numbers"""
if not isinstance(v, (int, float)):
raise ValueError(f"Value must be a number, got {type(v).__name__}")
return v

@field_validator('operator')
@classmethod
def validate_operator(cls, v):
"""Ensure operator is supported"""
valid_operators = ['+', '-', '*', '/', '**', '%', '//']
if v not in valid_operators:
raise ValueError(f"Operator must be one of {valid_operators}, got '{v}'")
return v


class State(BaseModel):
"""Internal state for the calculator agent"""
a: Union[int, float]
b: Union[int, float]
operator: str
result: Union[int, float, str] = ""
error: str = ""


class Output(BaseModel):
"""Output schema for calculator agent"""
result: Union[int, float, str] = Field(..., description="Result of the operation or error message")
operation: str = Field(..., description="The operation that was performed")
success: bool = Field(..., description="Whether the operation was successful")


def validate_inputs(state: State) -> State:
"""Validate that inputs are numbers and operator is valid"""
# Validation is handled by Pydantic, so if we get here, inputs are valid
return state


def perform_operation(state: State) -> State:
"""Perform the mathematical operation based on the operator"""
try:
a = state.a
b = state.b
operator = state.operator

# Perform the operation using match-case
match operator:
case '+':
result = a + b
case '-':
result = a - b
case '*':
result = a * b
case '/':
if b == 0:
return State(
a=a, b=b, operator=operator,
result="", error="Division by zero is not allowed"
)
result = a / b
case '**':
result = a ** b
case '%':
if b == 0:
return State(
a=a, b=b, operator=operator,
result="", error="Modulo by zero is not allowed"
)
result = a % b
case '//':
if b == 0:
return State(
a=a, b=b, operator=operator,
result="", error="Floor division by zero is not allowed"
)
result = a // b
case _:
return State(
a=a, b=b, operator=operator,
result="", error=f"Unsupported operator: {operator}"
)

return State(a=a, b=b, operator=operator, result=result, error="")

except Exception as e:
return State(
a=state.a, b=state.b, operator=state.operator,
result="", error=f"Error performing operation: {str(e)}"
)


def create_output(state: State) -> Output:
"""Create the output based on the operation result"""
operation = f"{state.a} {state.operator} {state.b}"

if state.error:
return Output(
result=state.error,
operation=operation,
success=False
)

return Output(
result=state.result,
operation=f"{operation} = {state.result}",
success=True
)


# Build the graph
builder = StateGraph(State, input=Input, output=Output)

# Add nodes
builder.add_node("validate", validate_inputs)
builder.add_node("calculate", perform_operation)
builder.add_node("output", create_output)

# Add edges
builder.add_edge(START, "validate")
builder.add_edge("validate", "calculate")
builder.add_edge("calculate", "output")
builder.add_edge("output", END)

# Compile the graph
graph = builder.compile()
39 changes: 4 additions & 35 deletions samples/calculator-agent/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,41 +1,10 @@
[project]
name = "calculator-agent"
name = "calculator"
version = "0.0.1"
description = "Calculator Agent"
description = "calculator"
authors = [{ name = "John Doe", email = "john.doe@myemail.com" }]
requires-python = ">=3.10"
dependencies = [
"uipath-langchain>=0.0.130",
"uipath>=2.1.54",
"uipath-langchain>=0.0.106",
"langchain-anthropic>=0.3.8",
]

[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"]
61 changes: 46 additions & 15 deletions samples/calculator-agent/uipath.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
{
"entryPoints": [
{
"filePath": "agent",
"uniqueId": "5e1d7bfd-c1b3-4d4f-bd0d-62e3b975e30b",
"filePath": "main",
"uniqueId": "7a8effb9-67f9-460e-8600-78cc2aaecef4",
"type": "agent",
"input": {
"type": "object",
"properties": {
"a": {
"title": "A",
"type": "number"
"anyOf": [
{
"type": "integer"
},
{
"type": "number"
}
],
"description": "First number",
"title": "A"
},
"b": {
"title": "B",
"type": "number"
"anyOf": [
{
"type": "integer"
},
{
"type": "number"
}
],
"description": "Second number",
"title": "B"
},
"operator": {
"enum": [
"+",
"-",
"*",
"/"
],
"description": "Mathematical operator: +, -, *, /, **, %, //",
"title": "Operator",
"type": "string"
}
Expand All @@ -36,9 +47,29 @@
"type": "object",
"properties": {
"result": {
"anyOf": [
{
"type": "integer"
},
{
"type": "number"
},
{
"type": "string"
}
],
"default": null,
"title": "Result"
},
"operation": {
"default": null,
"title": "Operation",
"type": "string"
},
"success": {
"default": null,
"title": "Result",
"type": "number"
"title": "Success",
"type": "boolean"
}
},
"required": []
Expand All @@ -49,4 +80,4 @@
"version": "2.0",
"resources": []
}
}
}
Loading