Scholia turns a course's lecture recordings, slides and assignments into a knowledge base that answers questions with citations to the exact lecture moment, slide or page, and helps you prepare for exams. The name comes from scholia, the notes scholars wrote in the margins of classical texts.
Live app: https://scholia.mol.la (click Try the demo, no sign-up; guest data is deleted after 48 hours)
Category and lane: Social good (Education) · Community. #social-good #community
You create a course, add lecture PDFs, audio, markdown notes and LaTeX (Overleaf) files, then chat with it. Each chat is tied to one course and one model. The assistant:
- answers questions from the course material, citing the page, slide or lecture moment, and uses the web (Tavily) when the material is thin;
- works through assignments step by step and reviews your answers against the course;
- runs mock exams, one question at a time, and grades each answer;
- refuses questions that aren't about the course, and handles abusive or harmful messages with a fixed, calm reply.
flowchart LR
user([Browser]) -->|HTTPS scholia.mol.la| cf[CloudFront<br/>ACM certificate]
cf -->|"/*" OAC| site[(S3<br/>site bucket)]
cf -->|"/api/*" OAC, SigV4| api[Lambda API<br/>Go, arm64]
user -->|presigned PUT| uploads[(S3<br/>uploads bucket)]
api --> cognito[Cognito<br/>email sign-in codes]
api --> ddb[(DynamoDB<br/>courses, chats, usage caps)]
api --> vectors[(S3 Vectors<br/>embeddings)]
api --> bedrock[Bedrock<br/>Nova 2 Lite, Titan V2,<br/>Guardrails]
api --> secrets[Secrets Manager<br/>session secret, Tavily key]
api --> ssm[SSM Parameter<br/>kill switch]
api -->|web search| tavily([Tavily])
uploads -->|ObjectCreated| sqs[SQS queue<br/>+ DLQ]
sqs --> worker[Lambda worker<br/>max 2 at once]
worker --> transcribe[Transcribe<br/>lecture audio]
transcribe -->|job state| eb[EventBridge] --> sqs
worker --> bedrock
worker --> vectors
worker --> ddb
worker --> uploads
kms{{KMS key}} -.encrypts.- ddb
kms -.- uploads
kms -.- secrets
cw[CloudWatch alarms<br/>Route 53 health check<br/>Budgets] --> sns[SNS<br/>alert email]
Account guardrails sit beside the app: CloudTrail (all regions), GuardDuty, IAM Access Analyzer and account-wide S3 Block Public Access.
| Service | Purpose |
|---|---|
| Amazon CloudFront | Serves the SPA and fronts the API on one domain; origin access control signs every request to S3 and the Lambda function URL, so neither is reachable directly |
| AWS Certificate Manager | TLS certificate for scholia.mol.la |
| Amazon S3 | Site bucket for the web build; uploads bucket for course files and chat attachments (presigned, size-signed PUTs; guest files expire after 3 days) |
| AWS Lambda | Go API behind a function URL, and the ingest worker that parses PDFs, slides, notes and transcripts |
| Amazon SQS | Queue between upload events and the worker, with a dead-letter queue for failed files |
| Amazon EventBridge | Sends Transcribe job completions back to the worker queue |
| Amazon Transcribe | Turns lecture recordings into timed transcripts, so answers cite the lecture moment |
| Amazon Bedrock | Nova 2 Lite for chat, Titan Text Embeddings V2 for retrieval, Guardrails for harmful content and prompt attacks |
| Amazon S3 Vectors | Stores and queries chunk embeddings per course |
| Amazon DynamoDB | Courses, sources, chats, messages and the daily usage caps |
| Amazon Cognito | Passwordless email sign-in codes |
| AWS Secrets Manager | Session signing secret and the Tavily API key |
| AWS Systems Manager Parameter Store | Kill switch that stops model calls without a redeploy |
| AWS KMS | Customer managed key for the table, uploads, secrets, logs and users' stored provider keys |
| Amazon CloudWatch | Logs, and alarms on Lambda errors, throttles and latency, the dead-letter queue, Bedrock throttles and token spend, and site health |
| Amazon Route 53 | Health check on the live URL |
| Amazon SNS | Delivers alarm and budget emails |
| AWS Budgets | Monthly cost budget with alerts |
| AWS IAM | Least-privilege roles per function, and the scholia-agent role the coding agent uses |
| AWS CloudTrail | Multi-region audit trail, including every call the coding agent makes |
| Amazon GuardDuty | Threat detection for the account |
| IAM Access Analyzer | Flags resources shared outside the account |
Everything is defined in Terraform under infra/terraform.
Scholia was built with Claude Code as the coding agent, connected to AWS through the AWS MCP server (mcp-proxy-for-aws, see .cursor/mcp.json).
Proof of the AWS connection
- The agent works in AWS as the IAM role
scholia-agentwith the session nameclaude-code. The role's trust policy enforces that name, so every action it takes shows in CloudTrail asassumed-role/scholia-agent/claude-code. assets/proof/cloudtrail-claude-code.jsonis the CloudTrail record of that session: 432 calls on launch day, including the creation of the Lambda functions, CloudFront policies, Bedrock guardrail, S3 Vectors index and Cognito pool, and later code deploys and checks. The account ID is masked.
Development process
- Plan: the agent read the codebase, reported the gaps, and proposed a plan. I approved each step and made the product decisions: sessions stored on the backend, attachments kept in the chat, a server-wide Tavily key, and the security scope.
- Build: the agent split the work into backend, frontend and infrastructure tasks and ran them in parallel against an agreed API contract. It adapted retrieval, attachment and trust-fence patterns from a sibling project.
- Verify: each change was checked in Docker with tests, a coverage gate, lint, gosec, and the Terraform validate, test, tflint, checkov and trivy checks, plus a smoke script run against the local stack.
- Ship: through the MCP connection the agent checked Bedrock model access and the Lambda quotas, and ran a Well-Architected review before the first apply. It ran
terraform planfor me to review, and the stack was applied asscholia-agent/claude-code. It looked up the certificate validation record for Cloudflare, published the web app and smoke-tested the live URL. It then used CloudWatch logs, Bedrock and guardrail metrics, andApplyGuardrailto find and fix three problems that only showed in production: streaming through the Lambda function URL, the vector index permission, and guardrail false positives on follow-up messages.
0 comments
log in to comment.