social-messaging-agent-runtime-toolkit / socialagent-admin-console
AGENTS.md4 starsChanged 8 days agoApache-2.0View on GitHub
Conversations, Schedules, State and Phone numbers are also per-stack Stack Detail tabs. User management (Cognito) is handled via the Terraform admin_emails variable / the backend users routes, not a dashboard page.
- Deletes or force-pushes
- Installs packages
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,774 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository14 other files it gives its agents.
- AGENTS.mdAGENTS.md
- blueprints/appointment-scheduler/AGENTS.mdAGENTS.md
- blueprints/minimal/AGENTS.mdAGENTS.md
- blueprints/personal-assistant/AGENTS.mdAGENTS.md
- recipes/generate-image/AGENTS.mdAGENTS.md
- recipes/rich-messages/AGENTS.mdAGENTS.md
- recipes/voice-reply/AGENTS.mdAGENTS.md
- blueprints/appointment-scheduler/CLAUDE.mdCLAUDE.md
- blueprints/minimal/CLAUDE.mdCLAUDE.md
- blueprints/personal-assistant/CLAUDE.mdCLAUDE.md
- CLAUDE.mdCLAUDE.md
- image_generationSkill
- rich_messagesSkill
- voice_replySkill
The file
We split this AGENTS.md into the rules it gives an agent
1 rule. About 0 are common, 1 is distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 45
All dangerous ops have confirmation modals
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
SMART Admin Console — AI/Developer Context
Quick Recovery
# from the repository root (the targets live in the root Makefile)
make ui-dev # Local dev with proxy
make ui-deploy # Full deploy pipeline
make ui-test # Frontend vitest suite
make backend-test # Backend pytest suite (backend/tests/)Architecture
- Frontend: React + Cloudscape (dark mode), Vite, TypeScript
- Backend: Single Python Lambda (
backend/handler.py, a thin dispatcher) — logic split intoroutes/<resource>.pymodules (one per resource) andshared/*.pyhelpers; routing via AWS Lambda PowertoolsAPIGatewayHttpResolverdecorators.shared/config.pyis the home for env-var reads (shared/auth.pystill reads its own Cognito settings). Authorization is the@require_groupdecorator fromshared/auth.pyon every route, directly under the route decorator — there is no global middleware;backend/tests/unit/test_route_authorization.pyfails on a route that lacks it, has it in the wrong order, or changes level - Auth: Cognito User Pool + Identity Pool, Amplify
<Authenticator> - Infra: Terraform modules:
frontend/(S3+CloudFront+OAC),auth/(Cognito),api/(APIGW+Lambda+DynamoDB+S3)
Pages (10 top-level + Stack Detail)
Top-level routes (NAV_ITEMS / renderPage in App.tsx): Overview, Stacks, Conversations, Schedules, State, Phone numbers, Events, Templates, Logs, Settings.
| Page | Route | Data Source |
| Overview | #/ | All stacks (cards) |
| Stacks | #/stacks | Registry + CloudWatch + AgentCore |
| Stack Detail | #/stacks/:id | Per-stack — 7 tabs (see below) |
| Conversations | #/conversations | AgentCore Memory (cross-stack) |
| Schedules | #/schedules | EventBridge Scheduler (every schedule in the region) |
| State | #/state | DynamoDB state tables (cross-stack) |
| Phone numbers | #/phone-numbers | Registry + EUM Social; bind/unbind lives only here |
| Events | #/events | CloudWatch Logs + trigger wizard |
| Templates | #/templates | EUM Social (cross-stack) |
| Logs | #/logs | CloudWatch FilterLogEvents |
| Settings | #/settings | DynamoDB settings table |
Conversations, Schedules, State and Phone numbers are also per-stack Stack Detail tabs. User management (Cognito) is handled via the Terraform admin_emails variable / the backend users routes, not a dashboard page.
Stack Detail Tabs (7)
Status, Conversations, Schedules, State, Phone Numbers, Deploys, Errors
Key Patterns
useApihook for consistent loading/error/refreshuseHashRouterfor hash-based routingsetAuthTokenProvider()hands the API client a per-request ID token resolver (TokenSync component)aws-exports.tsreadsVITE_*env vars baked at build time- All dangerous ops have confirmation modals
- Nuclear reset runs step-by-step from frontend with progress
- Admin-only actions call
usePermission("admin")(src/hooks/use-groups.ts), which reads thecognito:groupsclaim TokenSync provides, and passdisabled/disabledReasonto the control. It is presentation only:require_groupon the backend decides every request - Bulk deletes run through
deleteEach(src/api/bulk-delete.ts), which counts an item only once its call resolves, and counts an item whoseremoveresolves toNOT_FOUND(a state key the backend found nothing under, or a schedule whose delete answered 404) as not found, not deleted;deleteFlashreads "Deleted 1 key(s), 1 not found, 1 failed", an error with the backend's reason under the counts when anything failed and a warning when something was not found - The routes that read CloudWatch Logs (
PUT /api/logs,GET /api/stacks/<id>/errors,GET /api/stacks/<id>/events) answer{results, unreadable}.unreadablelists each Lambda whose log group was not read in full as{lambda, reason}, the reason an AWS error code orbudget(the request's calls or time ran out first); a log group that does not exist yet is no events, not unreadable. A route that read no group, with a call failed, answers502with the list, and log search answers400"Invalid filter pattern" without repeating the pattern. The client'stoLogRead(src/api/log-read.ts) also takes the bare list an older backend answers, and a page that lists log lines showsUnreadableLogsAlertand never its "No errors" or "No events" empty state whileunreadableis not empty or after a failed request, a502included - The manual mock
src/api/__mocks__/client.tsmust cover everyapimethod a component calls: a missing one makes the call throw, so a component test can pass on the error path for the wrong reason.ApiErrorlives insrc/api/errors.ts, which is not mocked, so code that tells statuses apart (instanceof ApiError) sees the real class in tests, and a test rejects withnew ApiError(message, status)to drive it
Backend Route Pattern
Routes are Powertools @app.get/put/post/delete decorators in backend/routes/<resource>.py, registered on the shared resolver in shared/resolver.py; handler.py imports the route modules and calls app.resolve. Path params use Powertools <name> placeholders (e.g. /api/stacks/<id>).
Auto-Registration
- A stack whose config sets
admin_registry_bucket(andadmin_registry_prefix) pushessocialagent.yamlto the registry viaaws_s3_objecton every deploy - Dashboard reads stack metadata from the S3 registry (
socialagent.yamlper stack)
Deployed Infrastructure
Environment-specific (CloudFront distribution, API Gateway, Cognito User/Identity Pools,
the S3 registry bucket, the backend Lambda). Resolve concrete names/IDs from
terraform output in socialagent-admin-console/infra-terraform/ or from the AWS console — never hardcode them here.
Lambda Deploy (when Terraform hash doesn't trigger)
# from the repository root
cd socialagent-admin-console/infra-terraform
rm -rf modules/api/.build/package && mkdir -p modules/api/.build/package
python3 -m pip install -r ../backend/requirements.txt -t modules/api/.build/package --quiet --no-compile --python-version 3.12 --platform manylinux2014_x86_64 --implementation cp --only-binary=:all:
cp ../backend/handler.py modules/api/.build/package/
cp -r ../backend/shared modules/api/.build/package/shared
cp -r ../backend/routes modules/api/.build/package/routes
rm -f modules/api/.build/backend.zip
(cd modules/api/.build/package && zip -r ../backend.zip . -q)
aws lambda update-function-code --function-name <env>-socialagent-admin-api --zip-file fileb://modules/api/.build/backend.zip
handler.pyimportsshared/androutes/at load time — all three must be in the package or the Lambda fails to import.routes/also carries the deny-by-default authorization decorators (shared/auth.py), so a partial copy would silently ship an unprotected or broken build.
Known Constraints
- AgentCore Memory has no "list all sessions" API — conversations discovered via DynamoDB scan
- EUM Social lists phone numbers per WABA:
GetLinkedWhatsAppBusinessAccountreturnsaccount.phoneNumbersfor each WABAListLinkedWhatsAppBusinessAccountsreturns. A number is bound where a registry entry'sphone_number_idnames it (its ARN or itsphone-number-id-…id) - One-shot EventBridge schedules auto-delete after firing (only recurring visible in Schedules page)
handler.pyis a thin dispatcher (under 50 lines); all logic lives inroutes/<resource>.py+shared/*.py. The Terraform packaging step (modules/api/main.tf) must copyroutes/into the Lambda zip and hash it in the redeploy trigger — a top-levelfrom routes import ...means a missing package = cold-start 502- Backend tests live in
backend/tests/(make backend-test); frontend has a vitest suite (make ui-test) src/api/client.tspasses every dynamic value in a request path throughsegment(), which URL-encodes it and refuses an empty,.or..segment; a new call must do the same.test/api/client.test.tscalls every path-building method with a hostile value, and it fails until a newapimethod is listed as path-building or constant-pathbackend/requirements.txtpinsboto3andbotocoreat 1.43.33 or later, the first botocore withFilterLogEventsstartFromHead, which the log search, Errors tab and Events page use to read the newest lines first. The SDK the Lambda runtime includes varies by Region and may be older, and on it the search falls back to reading window by window, which can miss the last minutes of a busy log group. Keep the floor; the SDK adds about 28 MB unzipped (16 MB zipped) to the package- The packaging step (
null_resource.backend_depsinmodules/api/main.tf) and the manual redeploy above installrequirements.txtfor the Lambda,--python-version 3.12 --platform manylinux2014_x86_64 --implementation cp --only-binary=:all:, matching the function's runtime and the Powertools layer (backend/tests/unit/test_package_target.pychecks all three agree). The host still needspython33.10 or later first on PATH, or pip 24.2 or later, since an older pip checks boto3'sRequires-Pythonagainst the host's Python;make backend-testneeds 3.10 or later package.jsonoverrides esbuild to^0.28.1: the 0.28.1 floor excludes GHSA-g7r4-m6w7-qqqr (esbuild >=0.27.3 <0.28.1, which Vite 7's^0.27.0 || ^0.28.0admits), so keep it, and the cap is the range Vite 7 declares. A Vite upgrade that changes Vite's esbuild range must revise the override in the same change. Forcing an esbuild outside the range Vite declares is what crashedmake ui-devunder Vite 6, and onlymake ui-smokecatches it;make ui-buildandmake ui-testdon't run Vite's dependency optimizer
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

