A browser-based agent that reads return tasks from Excel/Sheets, places returns on the relevant e-commerce platform (Amazon, Flipkart), and writes the outcomes back to the sheet per line item.
flowchart TD
%% Define Styles
classDef step fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px,color:#333
classDef start_end fill:#f5f5f5,stroke:#333,stroke-width:2px,color:#333
Start([1. Read Next Task]):::start_end --> OpenBrowser[2. Open Browser for Platform]:::step
OpenBrowser --> InitiateReturn[3. Initiate Return in UI]:::step
InitiateReturn --> Capture[4. Capture Status & Refund Amount]:::step
Capture --> WriteBack[5. Write Result Back to Sheet]:::step
WriteBack --> MarkDone([6. Mark Task as Done]):::start_end
The system is fully decoupled into three distinct layers to ensure fault tolerance, infinite lock-free scaling, and complete idempotency.
seed_queue.py reads the master queue.csv, filters out rows that are already in a terminal state, backs up the raw file to AWS S3, and pushes the pending line items individually to AWS SQS as JSON payloads.
An arbitrary number of run.py workers poll SQS. The worker routes the payload to the correct platform plugin (amazon.py or flipkart.py). It uses Playwright with stealth evasions to scrape the page, verifies eligibility (using date math or Groq LLM parsing), and stubs the final submit click. SQS dead-letters the message automatically after 3 failed attempts (ApproximateReceiveCount).
Upon reaching a terminal state (Success, Failed, or Needs human review), the worker appends the outcome locally to its own isolated file (outcomes_<PID>.csv). It simultaneously fires AWS CloudWatch metrics and Slack alerts. Finally, a separate cron job (sync_sheet.py) periodically sweeps all the isolated worker logs and updates the master queue.csv in a single thread-safe batch.
graph TD
%% Define Styles
classDef file fill:#f9f6f0,stroke:#d4c4a8,stroke-width:2px,color:#333
classDef aws fill:#ff9900,stroke:#232f3e,stroke-width:2px,color:#fff
classDef process fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px,color:#333
classDef external fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px,color:#333
classDef alert fill:#ffebee,stroke:#f44336,stroke-width:2px,color:#333
%% Ingestion Layer
subgraph Ingestion_Layer ["Ingestion Layer"]
CSV_In["queue.csv (Ops Source of Truth)"]:::file
SeedJob["seed_queue.py"]:::process
S3["AWS S3 (Backup)"]:::aws
CSV_In -->|Read Pending Rows| SeedJob
SeedJob -.->|Backup| S3
end
%% Queueing Layer
subgraph Queueing_Layer ["Queueing Layer"]
SQS["AWS SQS (BoomerangReturns)"]:::aws
SeedJob -->|Publish JSON Payload - Per SKU| SQS
end
%% Processing Layer (Scalable)
subgraph Worker_Pool ["Worker Pool (Horizontally Scalable)"]
Worker1["run.py (Worker PID: 101)"]:::process
Worker2["run.py (Worker PID: 102)"]:::process
WorkerN["run.py (Worker PID: N)"]:::process
SQS -->|Poll Message| Worker1
SQS -->|Poll Message| Worker2
SQS -->|Poll Message| WorkerN
end
%% Core Agent Logic (Inside Worker)
subgraph Agent_Core ["Agent Core"]
Browser["Playwright Stealth Browser"]:::external
LLM["Groq LLM (Fallback Parser)"]:::external
Platform["Amazon / Flipkart Plugin"]:::process
Worker1 --> Platform
Platform <--> Browser
Platform <--> LLM
end
%% Observability Layer
subgraph Observability_Alerting ["Observability & Alerting"]
CW["AWS CloudWatch"]:::aws
Slack["Slack Webhook"]:::alert
Worker1 -.->|put_metric_data| CW
Worker1 -.->|Needs human review| Slack
end
%% Output & Reconciliation Layer
subgraph Reconciliation_Layer ["Reconciliation Layer"]
Out1["outcomes_101.csv"]:::file
Out2["outcomes_102.csv"]:::file
OutN["outcomes_N.csv"]:::file
Worker1 -->|Lock-Free Append| Out1
Worker2 -->|Lock-Free Append| Out2
WorkerN -->|Lock-Free Append| OutN
SyncJob["sync_sheet.py (Cron)"]:::process
Out1 --> SyncJob
Out2 --> SyncJob
OutN --> SyncJob
Archive["data/archive/"]:::file
SyncJob -.->|Move Processed| Archive
SyncJob ==>|Batch Write-Back| CSV_In
end
Boomerang/
├── data/
│ ├── queue.csv # The master Ops spreadsheet
│ └── archive/ # Processed worker logs
├── src/
│ ├── platforms/
│ │ ├── amazon.py # Amazon batch/sequential logic
│ │ └── flipkart.py # Flipkart automation logic
│ ├── browser.py # Playwright Stealth Context manager
│ ├── decision.py # Regex + Groq LLM page state parser
│ ├── eligibility.py # Date math and window validation
│ ├── queue_manager.py # Core SQS worker loop & terminal status resolution
│ ├── logger.py # Structured JSON logging
│ ├── aws.py # Boto3 wrappers (SQS, S3, CloudWatch)
│ ├── alerts.py # Slack Webhook integrations
│ └── exceptions.py # Custom RateLimitException
├── tests/
│ ├── test_eligibility.py # Date math unit tests
│ ├── test_aws.py # Moto-mocked AWS tests
│ └── test_decision_demo.py # LLM/Regex fallback tests
├── run.py # Worker execution entrypoint
├── seed_queue.py # Ingestion script
├── sync_sheet.py # Batch write-back reconciliation script
├── requirements.txt
└── README.md
| Feature / Component | Status | Notes |
|---|---|---|
| Excel I/O | ✅ Implemented | Reading handled by seed_queue.py; lock-free batched write-back handled by sync_sheet.py. |
| Eligibility Math | ✅ Implemented | Handles 7/10/14-day string parsing and delivery date math robustly. |
| Dry-Run Loop | ✅ Implemented | Processes the SQS queue using full offline logic without opening Playwright. |
| Idempotency | ✅ Implemented | Safely detects already-handled returns to prevent double-submissions. |
| Bot-Detection Avoidance | Human-like session pacing, persistent browser context — reduces (not eliminates) detection risk. | |
| Amazon Batch Detection | ✅ Implemented | Dynamically detects Amazon's batch UI vs sequential flows. Not yet verified against a live multi-item order (see PRD §11). |
| SQS & Dead-Lettering | ✅ Implemented | Auto-drops to software DLQ after 3 failed ApproximateReceiveCount attempts. |
| CloudWatch & Slack | ✅ Implemented | Full observability wired into the worker loop. |
| Final Submit Click | Intentional safeguard. Stops right before clicking the final confirmation on both Amazon/Flipkart. | |
| Captcha/2FA | Automation pauses, waits for manual user terminal input() to solve CAPTCHA/OTP, then resumes. |
During earlier development phases, the following edge cases were discovered (and have since been patched, but are documented here for historical context of the system's evolution):
- The "5-6 July" date-parsing issue: The
dateutilparser initially misparsed "5-6 July" by defaulting the year to2005(since the hyphen confused the parser). This was fixed by aggressively pre-cleaning date strings to only keep the final valid day before passing them to the parser. - The cancellation-bypasses-delivery edge case: If an item was marked "Cancelled" by the user before it was ever delivered, the "Delivery date" column was often blank or invalid in the sheet. This caused the script to crash when trying to calculate the return window. This was fixed by adding a pre-check: if the
Statusstring contains "Cancelled", it skips the delivery date math entirely and marks it terminal.
- Install Dependencies
pip install -r requirements.txt playwright install chromium
- Environment Variables
Copy the example environment file and fill in your keys:
You will need a Groq API Key, a Slack Webhook URL, and valid AWS Credentials.
cp .env.example .env
You can run the pipeline directly on your local data/queue.csv without setting up any AWS infrastructure.
1. Dry-Run Mode (Local) Verify the offline date math and eligibility logic on the local queue:
python run.py --dry-run2. Live Automation Mode (Local) Run the browser automation worker on the local queue:
python run.py3. Reconciliation (Local) Reconcile worker output outcomes back to the master queue file:
python sync_sheet.pyTo run with horizontally scalable SQS queues and full AWS observability:
1. Seed the Queue Push pending tasks from your CSV to SQS:
python seed_queue.py --input data/queue.csv --queue-url "https://sqs.us-east-1.amazonaws.com/123456789012/BoomerangReturns"2. Dry-Run Mode (SQS) Test the SQS polling and offline date math logic:
python run.py --dry-run --queue-url "https://sqs.us-east-1.amazonaws.com/123456789012/BoomerangReturns"3. Live Automation Mode (SQS) Run the full browser automation worker polling the SQS queue:
python run.py --queue-url "https://sqs.us-east-1.amazonaws.com/123456789012/BoomerangReturns"4. Distributed Batch Sync (Reconciliation) Sweep distributed worker outcomes and batch sync them back to the master sheet:
python sync_sheet.pyRun the full test suite (covering mocked AWS calls, date logic, and NLP parsers):
python -m pytest tests/