Akhileshchandaluri/ai-procurement-test
AI Procurement Negotiation Agent
A deterministic OpenEnv-style benchmark for evaluating agent performance on real enterprise procurement negotiations.
This environment simulates a business process humans actually do: negotiating software and cloud contracts across multiple dimensions (price, SLA, support, payment terms) with constrained vendor behavior and explicit trade-offs.
Why This Environment Matters
Procurement teams negotiate high-value contracts under time pressure, with conflicting objectives and incomplete leverage. This project turns that workflow into a reproducible environment suitable for:
- Agent evaluation on realistic multi-step business decisions
- Reward shaping research on non-game, non-toy tasks
- Benchmarking deterministic vs LLM-assisted negotiation policies
Functional Requirements Mapping
1) Real-world task simulation
Implemented domain: software procurement negotiation.
Human-equivalent activity:
- Renewal negotiations
- Infrastructure procurement
- Multi-product bundle strategy
2) OpenEnv interface and typed models
The repository implements typed Pydantic models and environment methods:
- Typed action model:
NegotiationActioninmodels.py - Typed observation model:
NegotiationObservationinmodels.py - Typed state model:
NegotiationStateinmodels.py - Core methods in
environment.py: reset(task_name) -> NegotiationObservationstep(action) -> (observation, reward, done, info)state() -> NegotiationState- Metadata in
openenv.yaml
Validation command:
openenv validate3) Minimum 3 tasks with deterministic graders
Defined tasks in scenarios.py and openenv.yaml:
saas_renewalcloud_infra_dealenterprise_bundle
Programmatic graders in graders.py:
grade_pricegrade_supportgrade_paymentgrade_slagrade_bundle_trapgrade_episode
Scoring behavior:
- Continuous score range in [0.0, 1.0]
- Deterministic criteria (no randomness)
- Distinct negotiation structures from single-contract renewals to multi-product strategy
4) Meaningful reward function
Reward shaping is implemented in environment.py:
- Dense trajectory signal for incremental progress
- Positive reward for better negotiated terms
- Deterministic normalized scalar reward in [0.0, 1.0]
- Episode boundaries via done state and walkaway limits
5) Baseline inference script
Required script name exists at root:
inference.py
LLM OpenAI client baseline script:
inference_llm.py- Uses
openaiclient (from openai import OpenAI) - Uses env-configured model endpoint and credentials
- Emits structured logs in strict
[START],[STEP],[END]format
Task Workflows
Task 1: saas_renewal
How it works:
- The episode starts from an active SaaS renewal offer with baseline commercial terms.
- The agent iteratively proposes updates to price, payment terms, support tier, and SLA.
- The vendor simulator replies with accepted, countered, rejected, or walkaway outcomes based on policy limits.
- State tracks concessions won, current round, and live deal value signals so the policy can adapt over time.
What this task exercises:
- Controlled concession strategy over repeated rounds
- Trade-off handling between lower price and service commitments
- Term-structure planning instead of one-shot offer generation
Task 2: cloudinfradeal
How it works:
- The negotiation begins with a cloud infrastructure proposal where technical and commercial dimensions are tightly coupled.
- Each step allows the agent to refine package terms while reacting to vendor counter-moves.
- The simulator enforces stricter floor constraints and shorter walkaway windows, forcing realistic pacing.
- The trajectory reward reflects incremental progress across multiple dimensions, not just final acceptance.
What this task exercises:
- Multi-variable optimization under operational constraints
- Sequencing concessions to preserve leverage across rounds
- Robust policy behavior when vendor flexibility is limited
Task 3: enterprise_bundle
How it works:
- The environment presents a bundled enterprise offer across CRM, data platform, and security products.
- The agent can apply product-level strategy using
split_productswhen a bundle-level discount is not globally optimal. - Vendor logic evaluates both aggregate pricing pressure and product-level minimums before responding.
- History-aware grading rewards strategies that detect and act on the bundle structure instead of treating it as a flat quote.
What this task exercises:
- Portfolio negotiation across interdependent products
- Structural deal redesign (split vs bundle) under constraint checks
- Long-horizon negotiation planning with strategic decomposition
Action and Observation Spaces
Action model
NegotiationAction fields:
move: one ofpropose,accept,reject,counteroffer: optional structured terms payload (required forpropose/counter, optional foraccept/reject)justification: agent rationalesplit_products: optional list for bundle strategy
Observation model
NegotiationObservation fields:
vendor_responsecurrent_offervendor_messageround_numberconcessions_madedeal_value_so_faravailable_movestask_brief
Grading Logic
Standard task scoring (saas_renewal, cloud_infra_deal):
$$ \text{score} = 0.4\,\text{price} + 0.2\,\text{support} + 0.2\,\text{payment} + 0.2\,\text{SLA} $$
Bundle task scoring (enterprise_bundle):
- Strategy-aware grading via
grade_bundle_trap
All outputs are clamped to [0.0, 1.0].
Baseline Scores
Documented benchmark scores (from project verification artifacts):
saas_renewal: 0.583cloud_infra_deal: 0.744enterprise_bundle: 1.000- Average: 0.776
Environment Variables
Define these before running LLM inference:
API_BASE_URL: LLM API endpointAPI_KEY: API key/token used by OpenAI-compatible clientMODEL_NAME: model identifier
OpenAI client note:
inference_llm.pyinitializesOpenAIwithbase_url=os.environ["API_BASE_URL"]andapi_key=os.environ["API_KEY"].
Windows PowerShell:
$env:API_KEY="<your_key>"
$env:API_BASE_URL="https://router.huggingface.co/v1"
$env:MODEL_NAME="Qwen/Qwen2.5-72B-Instruct"Setup and Usage
Local setup
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtRun backend
uvicorn server.app:app --host 0.0.0.0 --port 8000Run interactive UI
python gradio_ui.pyRun deterministic baseline
python inference.pyRun LLM baseline with structured logs
python inference_llm.pyExpected log format:
[START] task=<task> env=<env_name> model=<model>
[STEP] step=<n> action=<action> reward=<float> done=<bool> error=<error_or_null>
[END] success=<bool> steps=<n> score=<float> rewards=<comma_separated_rewards>Docker and Hugging Face Space
Build and run container
docker build -t ai-procurement-negotiation-agent .
docker run -p 8000:8000 -p 7860:7860 ai-procurement-negotiation-agentContainer details:
- Dockerfile present and configured
- Exposes ports
8000(FastAPI) and7860(Gradio) - Health check endpoint at
/health
HF Space metadata is included in the YAML front matter at the top of this file and should remain unchanged.
OpenEnv Validation and Pre-Submission Checklist
Run these checks before submission:
openenv validate
python inference.py
python inference_llm.pyChecklist:
- HF Space deploys and returns 200
reset()andstep()respond correctlyopenenv.yamlvalidates- Docker builds cleanly
inference.pyruns to completion- 3 tasks execute with deterministic graders and scores in [0.0, 1.0]
- Inference runtime stays under 20 minutes on 2 vCPU / 8GB RAM
API Endpoints
FastAPI endpoints in server/app.py:
POST /resetPOST /stepGET /stateGET /health
Project Structure
environment.py: negotiation dynamics and reward shapingmodels.py: typed Pydantic models for action/observation/statescenarios.py: task definitions and constraintsgraders.py: deterministic scoring functionsinference.py: root baseline scriptinference_llm.py: OpenAI-client LLM baseline with structured logsserver/app.py: HTTP environment servicegradio_ui.py: user-facing simulation UIopenenv.yaml: environment metadataDockerfile: container runtime
Notes on Reproducibility
Determinism strategy:
- Rule-based vendor simulator (no random sampling)
- Deterministic grader functions
- Stable task configurations
This makes baseline outputs reproducible across repeated runs and suitable for leaderboard-style evaluation.
