Strands Skills support added to main agent with per-user S3 storage and upload UI

dropthejase adds Skills - user-uploaded markdown knowledge packages stored in S3 per user - to the main AgentCore agent. The agent downloads them to `/tmp` at session start and can read them on demand via a `read_local_file` tool. The storage format and upload validation are reusable independent of Strands.

chat-uiknowledge-management

Skills are folders with a SKILL.md manifest plus any reference files. Users upload a zip through the UI; the backend stores the files under a {userId}/ prefix in a dedicated S3 bucket. On session start, ensureSkillsDownloaded() checks whether the local /tmp/{userId}/skills/ directory is already populated and only fetches from S3 if it's empty. This is a reasonable caching strategy for the AgentCore microVM model, where the filesystem persists across turns within a session.

The AgentSkills plugin from @strands-agents/sdk/vended-plugins/skills is loaded with the local skills path and passed as a plugin to the Agent constructor. A read_local_file tool is also added - it accepts a relative path within the user's skills directory and enforces a path traversal guard, refusing any path that escapes skillsLocalBase(userId).

The UI polish commit (b135fc3) bumps text sizes from text-xs to text-sm in the folder tree and skill rows. Small change, but it signals the skills panel was being built for real use rather than demo purposes.

The doc clarification (0aa79de) is worth reading: the bundled EU AI System Classifier skill in the repo is a demo sample, not something that gets auto-seeded into user accounts. The earlier README said "seeds a sample", which would be surprising to users who didn't ask for it. The fix changes it to "shows a demo".

So what Worth a look if you want to give users a persistent knowledge injection surface without polluting the system prompt on every turn. The S3 per-user prefix layout, the `ensureSkillsDownloaded` caching pattern, and the path traversal guard in `read_local_file` are the pieces worth taking. The Strands plugin dependency is specific to this fork's agent SDK; the storage pattern is not.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

5 commits from dropthejase/louis, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
5641aca5 feat(skills): full Strands Skills support for louisMain agent Jason Lee 2026-05-15 ↗ GitHub
commit body
Full-stack implementation of read-only knowledge injection via Strands Skills.

Infra:
- storage-stack: skillsBucket (S3, BLOCK_ALL, CORS GET/HEAD/PUT for CF domain)
- api-stack: SKILLS_BUCKET_NAME env, grantReadWrite to API Lambda, read-only S3 policy on AgentCore role
- bin/app.ts: wire skillsBucket into ApiStack

Agent:
- lib/skills.ts: ensureSkillsDownloaded - lists S3 prefix, downloads to /tmp/<userId>/skills/, skips if cached
- tools/read-local-file.ts: path-sandboxed file reader, returns ImageBlock/DocumentBlock for supported types
- agent.ts: AgentSkills plugin (vended-plugins/skills), read_local_file tool, skillsBase param
- index.ts: ensureSkillsDownloaded runs in parallel with doc context + history load

API:
- routes/skills.ts: GET /skills, POST /skills/prepare, DELETE /skills/:skillName,
  GET /skills/:skillName/files, GET /skills/:skillName/file (presigned GetObject)

Frontend:
- SkillsList: folder-browser UI with virtual tree built from flat S3 paths,
  expandable skill rows (Puzzle icon), amber folder icons for subdirs,
  file viewer modal (image/PDF/text; "Preview not supported" for others),
  right-click context menu delete, upload validation (SKILL.md required,
  name must match folder name)
- mikeApi: listSkills, getSkillUploadUrl, deleteSkill, listSkillFiles, getSkillFileUrl
- App.tsx + AppSidebar: /skills route + nav item

Scripts:
- deploy-agent.sh: reads SkillsBucketName from CFN, passes as SKILLS_BUCKET_NAME to AgentCore
b135fc31 feat(skills): skills UI polish - font sizes, folder tree, file viewer, upload validation Jason Lee 2026-05-15 ↗ GitHub
commit body
- Bump description, file tree, info banner to text-sm (matches Projects/Workflows)
- Virtual folder tree from flat S3 paths (amber folder icons, expandable)
- File viewer modal: image/PDF/text preview; unsupported formats show message
- Right-click context menu delete; puzzle icon for skill rows
- Upload validates SKILL.md name matches folder name client-side
- Fix horizontal scroll (min-w-max → w-full); fixed height rows (h-14)
12445c9b feat: merge feature/skills - full Strands Skills support Jason Lee 2026-05-15 ↗ GitHub
commit body
Skills = read-only knowledge injection for louisMain. Users upload skill folders
via /skills page. Agent downloads to /tmp on session start, discovers via AgentSkills
plugin, reads reference files via read_local_file tool. No bash tool (MMDS risk).

Commits: 5641aca (core), b135fc3 (UI polish), 82dd664 (sharing buttons)
4a6d8664 docs(readme): add Additional Features section for Strands Skills Jason Lee 2026-05-15 ↗ GitHub
0aa79dee docs: clarify skill is demo sample not auto-seeded Jason Lee 2026-05-16 ↗ GitHub

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-352.md from inside the repo you want the changes in.

⬇ Download capture-thread-352.md