Diagnosing and Resolving the JADA Agent Orchestrator: Daemon Health, OAuth Token Failures, and Multi-Site Deployment Patterns
This post covers a complete health audit of the JADA agent daemon running on AWS Lightsail (34.239.233.28), the discovery of a broken Google OAuth token in the port sheet sync routine, and the operational patterns observed across multiple website deployments during a single development session.
What Was Done
- Diagnosed the
jada-agent.servicedaemon health via SSH and metrics collection - Identified a persistent OAuth 400 error in the
port_sheet_sync.pyGoogle token authentication - Analyzed three agent sessions from 2026-05-13, including two that hit the 30-turn Claude limit
- Deployed fixes to multiple static sites: 86from.com, sailjada.com, and queenofsandiego.com
- Migrated directory structure (86dfrom.com → 86from.com) and updated S3/CloudFront caches
Daemon Health: The Good News
The jada-agent.service is operationally sound. The service has been running continuously for 3 days (since May 10) with 11 days of instance uptime. Key metrics:
- CPU utilization: 0.65% average over the polling window—essentially idle between task executions
- Memory footprint: 144MB / 914MB available—well within healthy bounds
- Disk usage: 6.2GB / 39GB (17%)—plenty of headroom for logs and task artifacts
- Load average: 0.00, indicating the daemon's 60-second polling loop is lightweight
- AWS status checks: 0 failures in the last 2 hours
The daemon is successfully pulling tasks from the progress dashboard and executing them. On 2026-05-13, three sessions were consumed (3 of 5 daily limit), with one completing successfully and two hitting the 30-turn Claude context limit.
Session Analysis: May 13 Activity
Session 1 (00:00 UTC): Exited with code 1 after reaching the 30-turn limit. The daemon logged this as an error condition but continued operation—not a crash.
Session 2 (00:02 UTC): Completed successfully. This session processed e-signature and crew page generator blockers and created a needs-you task flagging issues with the e-signature link and crew page generation logic.
Session 3 (00:05 UTC): Again hit the 30-turn limit and exited with code 1. After this session, no new tasks were queued; the daemon returned to idle polling.
Yesterday's pattern: At 2026-05-12 23:59 UTC, the daemon hit a hard stop after consuming all 5 daily sessions with 3 pending tasks still in the queue. At midnight rollover (start of UTC day), the session count reset and pending tasks cleared—expected behavior given the session quota system.
Critical Issue: Broken Google OAuth Token in port_sheet_sync
Every 30-minute sync invocation of port_sheet_sync.py has been failing since at least afternoon on 2026-05-13. The error:
[port-sheet] token error: HTTP Error 400: Bad Request
The Google OAuth token used by port_sheet_sync.py is either expired or has been revoked. This prevents the port sheet synchronization from running. The script likely reads the token from a stored credentials file (possibly in /home/jada/.config/google/ or a similar secrets directory on the Lightsail instance), and that token is no longer valid.
Root cause: Google OAuth tokens have a finite lifetime. When the initial auth token was generated (via the OAuth 2.0 authorization code flow with google-auth-oauthlib), the token came with an expiration timestamp and a refresh token. Either the token has aged beyond its lifetime and the refresh token is stale, or the token was explicitly revoked (e.g., via Google Account security settings).
Impact: The port sheet—likely a Google Sheet used for tracking bookings, crew assignments, or scheduling—is no longer being synced to the internal system. Any updates made to that sheet in the last 24+ hours are not reflected downstream.
Infrastructure & Deployment Patterns
During this session, multiple sites received updates with a consistent deployment pattern:
- 86from.com: Directory renamed from
86dfrom.comto86from.comin the repos tree. New SEO page created at/Users/cb/Documents/repos/sites/86from.com/site/what-does-86d-mean. Files pushed to S3 and CloudFront cache invalidated. - sailjada.com: Multiple iterative edits to
index.html(13 separate edits logged). Likely refinement of booking widget or layout. Deployed via the standard pipeline. - queenofsandiego.com: Updated
BookingAutomation.gs(a Google Apps Script file) twice. This is a server-side automation script for the queen-of-sandiego booking system.
Booking widget issue resolved: The sailjada.com edits included fixing double-brace syntax errors ({{ and }}) within the booking widget JavaScript section. The issue: double braces outside a template context were being interpreted as template delimiters rather than literal characters. The fix involved isolating the booking widget's script block and replacing problematic braces with single braces where appropriate, then validating the JavaScript syntax before deployment to the staging bucket and production CloudFront distribution.
Auth tooling: A new auth_ga.py script was created in /Users/cb/Documents/repos/tools/ to handle Google Analytics API authentication and token management. This tool uses the google-auth-oauthlib library to generate OAuth tokens for Analytics Data API access. During the session, this script was used to list GA4 accounts and properties under the dangerouscentaur@gmail.com account and to pull 7-day traffic reports for 86dfrom.com (before the directory rename).
Key Decisions & Architectural Notes
Lightsail API for temporary SSH access: Because the persistent jada-key was not available in the local SSH directory, the session used the AWS Lightsail API to generate temporary SSH credentials. This is more secure than hardcoding private keys and allows for time-limited access without managing static key material.
Session limits and turn limits: The daemon respects two limits: a daily session quota (5 sessions/day) and a per-session turn limit (30 turns). When the 30-turn limit is hit, the daemon exits cleanly with code 1 rather than crashing or hanging. This is intentional—it prevents a single task from monopolizing the Claude API quota. However, it means complex tasks may require multiple sessions or scope reduction.
OAuth token lifecycle: The port_sheet_sync.py` failure highlights the importance of token refresh logic. If a script relies on a stored OAuth token without implementing refresh-token handling, it will fail once the