A stateful, backend-only agent that assists Construction Site Managers with procurement decisions. Built with Google ADK + Gemini, but designed so the LLM is a reasoning component, not a rule engine.
It has exactly two jobs:
- Remember rules — persist site-specific policies (approval limits, banned vendors) to a JSON file
- Enforce them deterministically — filter vendors, pick cheapest, pause if cost exceeds limits
The LLM (Gemini) only parses user intent and extracts fields. All business logic is pure Python.
┌─────────────────────────────────────────┐
│ Agent Layer │
│ (Gemini via ADK — intent parsing) │
├──────────┬──────────┬───────────────────┤
│ Memory │ Tools │ State │
│ Layer │ Layer │ Layer │
│ │ │ │
│ JSON R/W │ Vendor │ Pause/Resume │
│ │ filter + │ for approval │
│ │ cheapest │ │
└──────────┴──────────┴───────────────────┘
| Layer | File | Responsibility |
|---|---|---|
| Memory | agent/memory.py |
Read/write site rules to data/memory.json |
| Tools | agent/tools.py |
Load vendors, filter banned, select cheapest |
| State | agent/state.py |
Generate AWAITING_APPROVAL pause state |
| Agent | agent/agent.py |
ADK agent definition, tool registration |
| Entry | main.py |
Two-turn scripted demo |
intelligent-procurement-agent/
├── agent/
│ ├── __init__.py # Exports root_agent for ADK
│ ├── agent.py # ADK agent orchestration
│ ├── memory.py # Persistent rule storage (JSON)
│ ├── tools.py # Deterministic vendor logic
│ └── state.py # Pause / resume handling
├── data/
│ ├── memory.json # Runtime rule store (starts empty)
│ └── mock_vendors.json # Static vendor data (never changes)
├── docs/
│ └── work.txt # Statement of Work
├── main.py # CLI entry point
├── requirements.txt
├── .env # GOOGLE_API_KEY (not committed)
└── README.md
- Python 3.12+
- A Google API key (get one here)
# Clone
git clone https://github.com/STiFLeR7/CloudRedux-Assignment.git
cd intelligent-procurement-agent
# Create venv & install
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # macOS/Linux
pip install -r requirements.txtCreate a .env file in the project root:
GOOGLE_API_KEY=your-key-here
python main.pyRuns two turns automatically:
- Turn 1: Stores Pune site rules (limit ₹40,000, bans BadRock Cements)
- Turn 2: Orders 100 bags of cement → selects GoodRock → pauses (cost exceeds limit)
adk web .Open http://localhost:8000/dev-ui/ in your browser. Select agent from the dropdown and chat interactively.
User: "For the Pune site, the maximum approval limit is ₹40,000 and we strictly avoid 'BadRock Cements'."
What happens:
- Gemini extracts: site=Pune, limit=40000, banned=["BadRock Cements"]
store_site_rules()writes todata/memory.json- Rules persist across sessions
User: "Order 100 bags of cement for the Pune site."
What happens (all deterministic, no LLM):
- Reads Pune rules from
memory.json - Loads vendors from
mock_vendors.json - Filters out BadRock Cements (banned) — even though it's cheapest at ₹35,000
- Selects GoodRock (cheapest valid vendor @ ₹42,000)
- ₹42,000 > ₹40,000 limit → returns
AWAITING_APPROVAL
| Decision | Rationale |
|---|---|
| JSON file for memory | Intentionally visible I/O; no hidden state |
| Deterministic vendor logic | Business rules must not depend on LLM mood |
| Pause as a state, not failure | Models real enterprise approval workflows |
| Gemini only parses intent | LLM is a reasoning component, not a rule engine |
| No extended context reliance | Memory is architectural, not model-dependent |
| Relative imports | Clean package structure, works with ADK web |
| LLM Does | LLM Does NOT |
|---|---|
| Parse "Pune site" from natural language | Decide which vendor to pick |
| Extract approval limit from text | Approve or reject orders |
| Understand "order cement" intent | Store or retrieve rules |
| Route to the correct tool | Calculate costs |
- Memory —
write_site_rules/read_site_ruleswith JSON persistence - Deterministic logic — vendor filtering, cheapest selection, no AI
- Pause state —
AWAITING_APPROVALwith structured metadata - Agent orchestration — ADK Agent with two tool functions
- ADK integration —
root_agent,adk web, CLI runner - Polish — README,
.gitignore, clean structure
Run the CLI demo and verify:
| Scenario | Expected Outcome |
|---|---|
| Store Pune rules | memory.json contains approval_limit + banned_vendors |
| Order with banned vendor filtered | BadRock excluded, GoodRock selected |
| Cost exceeds limit | Status = AWAITING_APPROVAL |
| Cost within limit | Status = APPROVED |
| No rules set for site | Status = ERROR |
| All vendors banned | Status = REJECTED |
- Google ADK (Agent Development Kit)
- Gemini 2.0 Flash via Google AI Studio
- Python 3.12
- JSON for persistent memory
This implementation prioritizes clarity, control, and correctness over surface-level sophistication. The goal is not to show what the model can do, but to demonstrate how agentic systems should behave in real enterprise environments.