Releases: teslashibe/agent-setup
v0.8.0 — Optional Android notification capture (ambient communication rollup)
Optional ambient communication rollup for Android
Adds an opt-in feature that captures device notifications on Android via NotificationListenerService, ships them to a Timescale hypertable, and exposes 5 MCP tools so the agent can produce daily "what happened / what needs attention" rollups across SMS, WhatsApp, Zillow, email and any other allowlisted app.
Designed for the real-estate-agent persona but template-generic — every surface (DB rows, API routes, MCP plugin, system prompt, mobile UI) is gated by NOTIFICATIONS_ENABLED (server) and EXPO_PUBLIC_NOTIFICATIONS_ENABLED (client), default OFF, so forks that don't need it pay zero overhead.
What's in it
Backend
migrations/00003_notification_events.sql— Timescale hypertable + dedup unique constraint + content FTS indexinternal/notifications— store / service / handler with limit clamping, classification heuristics, full-text search viaplainto_tsqueryinternal/notifications/mcp— 5 tools (list,search,threads,apps,pending_actions) registered as the credential-lessnotificationsplatforminternal/mcp—PlatformBinding.NoCredentials+withUserID/UserIDFromContextso credential-less plugins can scope queriesagent.NotificationsSystemPrompt()rollup addendum, attached only when the flag is on- Per-user rate limiter on
/notifications/batch
Mobile (Android)
- Local Expo module
mobile/modules/notification-capture— KotlinNotificationListenerService+SharedPreferencesbuffer + JS bridge services/notificationSync.ts— foreground 5-min flush loop + AppState-driven sync, network-loss-safe viarequeueEventsproviders/NotificationCaptureProvider+app/(app)/capture.tsxsettings screen with master toggle, permission CTA, allowlist editoreas.json—preview+production-apkprofiles +npm run build:apk:*scripts
Verification
go vet ./..., go build ./..., go test ./... — all 11 packages green; npm run typecheck clean; expo prebuild --platform android succeeds; autolinking confirms the local module is discovered.
Audit per .claude/rules/issue-audit-user-stories.mdc caught and fixed two medium findings (network-failure data loss in flushNow; credential-less platform 500s in mcp.Server.resolveClient) before merge — see .cursor/tickets/notification-capture-audit.md.
Out of scope (V2)
iOS (OS-level restriction), background WorkManager sync, encrypted-at-rest buffer (needed if we go enterprise).
PR
v0.7.0 — Optional local code-generation agent (codegen-go)
Adds an opt-in local-execution path for the Claude Code CLI (and any other "prompt-on-stdin, edit-files-in-cwd" CLI like Codex / Aider / OpenHands / Cline / your-own) via the new teslashibe/codegen-go module. Closes #18.
Complementary to — not a replacement for — the Anthropic Managed Agents path shipped in v0.6.0. Managed Agents stays the default for chat-style agent products.
When you'd reach for the local path
The new path is for cases where the agent needs to:
- Run on this machine (filesystem access, on-prem, off-platform tools).
- Drive a non-Anthropic CLI you've already integrated with.
- Operate inside a long-running process under your direct control (e.g. an agent loop that opens PRs, like Eva Board's).
If your product is "user types in mobile, agent replies", stick with Managed Agents — nothing in this release touches that flow.
What's new
- New dependency
github.com/teslashibe/codegen-go v0.1.1. backend/internal/codegen/codegen.go— ~100-LoC shim:LoadFromEnv()readsCODEGEN_*env vars and returns a configuredAgent.- Re-exports
Agent,Config,Resultso callers stay on a single import path.
backend/internal/codegen/codegen_test.go— defaults / generic / missing-command / CSV-parser coverage.backend/cmd/codegen-demo/main.go— runnable proof:go run ./backend/cmd/codegen-demo "Summarise this directory in one paragraph."- Opt-in
CODEGEN_*block inbackend/.env.example(commented out by default). - New "Local code-generation agent (optional)" section in
README.mdexplaining when to reach for it and how to wire it in.
What's unchanged
- Managed Agents flow:
cmd/provision,internal/agent, the SSE event shape, every API route — all identical. - MCP server + 14 platforms / 374 tools from v0.6.0 — untouched.
- Teams / magic-link invites from v0.5.0 — untouched.
- All 9 backend test packages green (including the new
internal/codegensuite).
Configuration
# backend/.env — entirely optional
CODEGEN_AGENT=claude-code # or "generic" for any CLI
CODEGEN_MODEL= # optional --model override forwarded to claude
CODEGEN_TIMEOUT=30m
CODEGEN_MAX_OUTPUT_BYTES=10485760
CODEGEN_COMMAND= # required when CODEGEN_AGENT=generic (e.g. "codex", "aider")
CODEGEN_ARGS= # comma-separated argv prepended to the generic CLIPrerequisite for the default path: claude on PATH and claude login already done.
Upgrade
git pull
cd backend && go mod tidy && go build ./...Nothing required if you don't want the local path — the shim is a no-op until you set CODEGEN_AGENT.
Companion releases
teslashibe/codegen-gov0.1.1 — the new public module.EvaEverywhere/eva-boardv0.2.0 — the original producer, now a consumer of the same module.
v0.6.0 — MCP integration (374 tools / 14 platforms)
First release with the full Model Context Protocol integration that drives Anthropic Managed Agents on per-user, per-platform credentials. Closes #6.
Highlights
- MCP server in-process — Fiber routes at `POST /api/mcp/v1` (header JWT) and `POST /mcp/u//v1` (URL-path JWT for Anthropic Managed Agents), JSON-RPC 2.0 over HTTP, batch support.
- 374 fine-grained tools across 14 platforms — LinkedIn, X, X-Viral, Reddit, Reddit-Viral, Hacker News, Facebook, Instagram, TikTok, Threads, Product Hunt, Nextdoor, ElevenLabs, Codegen/Claude Code. Every `*Client` method is wrapped or in a coverage-tested exclusion list.
- Per-user encrypted credentials — `platform_credentials` table (AES-GCM, key from `CREDENTIALS_ENCRYPTION_KEY`); `POST/GET/DELETE /api/platforms/:platform/credentials` + `GET /api/platforms` for the connection-status grid.
- Per-user Anthropic Agent + Environment provisioned lazily on first session, IDs cached on `users.anthropic_*`. Each agent points at the user's own `/mcp/u//v1` endpoint so credentials never cross tenants.
- Server-side response shaping — `limit=10` default, `max=50`, 800-char rune truncation, 64 KB compact-JSON ceiling with iterative shrink + final `_truncated` marker.
- Settings → Platform Connections mobile screen, with both field-by-field input and Cookie-Editor JSON / raw `Cookie:` paste; reconnect CTA in chat when MCP returns `credential_*`.
- Drift-prevention — shared `mcptool` contract, schema-from-Go-structs, `TestEveryClientMethodIsWrappedOrExcluded` in every scraper, Dependabot bumps for all 15 mods, `nightly-deps.yml` workflow that opens a `dependency-drift` issue on first failure, and a Cursor rule (`.cursor/rules/mcp-tool-conventions.mdc`) that guides any AI editing the MCP layer.
Bugs found and fixed during the audit
- `ResponseShaper` infinite-recursed on numeric values (would have crashed every tool that returned a number).
- `truncated:true` flag was never set on paged responses, so agents had no signal to re-call with a cursor.
- `credentials.Service.Platforms()` returned an unordered slice.
All shipped with regression tests.
What's not in this release
- Live-credential end-to-end smoke tests for all 14 platforms (deferred to a follow-up issue).
- Credential-rotation / refresh-token flow (out of scope per spec).
- Browser extension that pushes cookies directly into the API (out of scope per spec).
Operator notes
- Set `CREDENTIALS_ENCRYPTION_KEY` (32 bytes, base64) before starting the API; without it the MCP routes are skipped at boot.
- Set `MCP_PUBLIC_URL` (or `APP_URL`) so the per-user MCP URL embedded in each Anthropic Agent is reachable.
- Run the new migration: `make migrate` (creates `platform_credentials` and adds `users.anthropic_*`).
v0.5.0 — Teams
Teams — owners, admins, members + magic-link invites
This release adds first-class multi-tenancy to the agent-setup template. Every user now sits inside one or more teams; agent sessions, invites, and the API surface are all team-scoped.
Highlights
- Roles:
owner/admin/member, enforced server-side and mirrored in the mobile UI via a singlecan(action)table. - Personal teams: auto-created on first login so single-user installs keep working with zero config.
- Magic-link invites: invite by email → recipient gets a one-time link → magic-link sign-in auto-accepts on success. No separate accept flow.
- Active team selection:
X-Team-IDheader drives request scoping; mobile remembers the choice across cold starts and exposes a tappable settings switcher. - Feature flag:
TEAMS_ENABLED(server) +EXPO_PUBLIC_TEAMS_ENABLED(mobile) toggle the whole feature on/off without breaking deep links.
Backend (Go / Fiber)
- New
internal/teamsandinternal/invitespackages with thin handlers, transactional store, and a service layer that enforces seat limits across both members and pending invites. - New migration
00002_teams.sqladdsteams,team_members,team_invites, scopesagent_sessionstoteam_id, and threadsinvite_tokenthroughauth_codes. - Spec-shaped HTTP surface:
GET /api/teams/,POST /api/teams/,PATCH /api/teams/:teamID/,DELETE /api/teams/:teamID/DELETE /api/teams/:teamID/members/me(leave),PATCH/DELETE /api/teams/:teamID/members/:userID,POST /api/teams/:teamID/transfer-ownershipGET/POST/DELETE /api/teams/:teamID/invites,POST /api/teams/:teamID/invites/:inviteID/resend- Public:
GET /api/invites/:token(preview),GET /invites/accept(deep-link landing) - Authed:
POST /api/invites/:token/accept
- Concurrent-accept correctness via
SELECT … FOR UPDATE(race-tested with 10 parallel attempts; exactly one wins). - Rate limits via
fiber/limiter: invite create per (team, hour), preview/accept per IP per minute. All four limits configurable via env. - Custom magic-link handlers plumb
invite_tokenend-to-end so the invite is consumed atomically with login.
Mobile (Expo / React Native)
TeamsProviderexposescan(action)/canIn(membership, action)over a singleresolveCantable that mirrors server-side gates.TeamPageProvidershares per-team data across the new sub-routes so navigation doesn't refetch.- New UI primitives:
RoleBadge,Select<T>,Dialog— replaces ad-hocAlert.alertand<Pressable><Badge/></Pressable>patterns; works on web (Alert.alert does not). - Spec-shaped route layout under
app/(app)/teams/:_layout.tsx·index.tsx·new.tsx[id]/_layout.tsx·[id]/index.tsx(overview) ·[id]/members.tsx·[id]/invites.tsx
- Invite landing screen with deep-link handoff to magic-link sign-in;
(auth)/invitealias for direct-from-auth entry. - Settings → Teams card now tappable, opens a team switcher modal (no need to bounce out to Manage teams).
Configuration
| Variable | Default | Purpose |
|---|---|---|
TEAMS_ENABLED |
true |
Server: gate /api/teams + /api/invites |
TEAMS_DEFAULT_MAX_SEATS |
25 |
Per-team seat cap (counts members + pending invites) |
TEAMS_INVITE_TTL_HOURS |
168 |
Invite token lifetime |
TEAMS_INVITE_FROM_NAME |
(operator) | Display name on invite emails |
TEAMS_INVITE_RATE_LIMIT / _WINDOW_SECONDS |
10 / 3600 |
Per-team invite-create cap |
TEAMS_ACCEPT_RATE_LIMIT / _WINDOW_SECONDS |
5 / 60 |
Per-IP preview/accept cap |
EXPO_PUBLIC_TEAMS_ENABLED |
true |
Mobile: hide Teams tab + switcher when false |
Docs
- New
docs/TEAMS.md— operator/integrator handbook (role matrix, invite lifecycle, magic-link bridge, end-to-end smoke test, disabling the feature). README.mdupdated with the new env vars and routes table.
Tests
- 11 new HTTP-level handler tests pin the spec-shaped routes (path-token + legacy aliases for both preview and accept).
TestConcurrentAcceptproves the invite-acceptance race invariant under-race.- Existing auth + agent suites updated for team scoping.
Closes
- #5 — feat: teams (owner / admin / member)
v0.4.0 — Platform-aware mobile sidebar
The mobile app now adapts its navigation to the form factor: iOS and Android keep the floating bottom tab bar, while the web build paints a fixed left sidebar that reads like a proper desktop app.
What changed
FloatingTabBar is now platform-aware. It splits into two branches sharing the same icon/label maps:
NativeBottomBar(iOS/Android) — the existing floating, absolutely-positioned bottom bar with safe-area inset.WebSidebar(web) — a 240px fixed-position left rail with the Claude Agent Go title, vertical route list, and an active-state pill.
(app)/_layout.tsx reshapes the layout per platform. On web it sets sceneStyle.marginLeft: 240 so screens flow into the viewport to the right of the sidebar instead of rendering underneath it. Native behavior is unchanged.
Routes without an iconMap entry are now skipped in both renderings, so hidden routes like chat no longer leak into the sidebar.
Dev convenience
Added an opt-in EXPO_PUBLIC_DEV_BYPASS_AUTH escape hatch in the root index and the (app) layout. When set to true (e.g. in .env.local), the web preview lands in the (app) shell without going through the magic-link flow — handy for previewing UI without a backend. Unset by default; impossible to enable in a production build.
Verified
tsc --noEmitclean.- Web build (
npm run web) renders the sidebar with active-state highlighting on/(Chats) and/settings, and pushes content right by 240px so nothing renders under the rail.
v0.3.1 — Infra-agnostic deployment
Small cleanup release on top of v0.3.0.
What changed
Removed deploy/ folder. The generic fly.toml, railway.toml, cloudrun.md, and k8s/ starters were boilerplate nobody actually used. Each deployer wires this template into their own infrastructure however they prefer.
What the README now says about deployment
- The container image builds and pushes to GHCR automatically on every commit to `main` and on tags via `.github/workflows/docker.yml`
- Required env vars are documented (Anthropic IDs, JWT_SECRET, DATABASE_URL, Resend, etc.)
- Run order: `/bin/migrate up` then `/bin/server`
- Database requirement: Postgres 16 + TimescaleDB extension
Repo footprint
Top-level is now: `LICENSE`, `Makefile`, `README.md`, `backend/`, `docker-compose.yml`, `mobile/`. That's it.
Verified
`go build`, `go vet`, `go test ./...` all clean.
v0.3.0 — Production-ready Claude Managed Agents seed
v0.3.0 — Production-ready Claude Managed Agents seed
This is the first release we'd actually ship to a paying client. The repo is now a
single-purpose, opinionated, deeply-tested template for building autonomous
Claude-powered products end-to-end.
It supersedes the v0.1.x and v0.2.x line. Everything from those releases has
been consolidated, validated, and where appropriate, replaced.
What this repo is
A GitHub Template Repository that lets you spin up a complete Claude-agent
product for a client in roughly a day:
- Go backend (Fiber v2) with magic-link auth and a TimescaleDB session store
- Expo app (iOS, Android, and web from one codebase) with a streaming chat UI
- Claude Managed Agents doing the actual agent work — bash, web search, file
ops, and code execution come for free; you just write a system prompt - Four deploy targets wired up: Fly.io, Railway, GCP Cloud Run, Kubernetes
- One DB migration — we're in dev, the schema lives in
00001_init.sql - ~1,150 lines of Go — every line earns its keep
The big shift since v0.1.x: Claude Managed Agents
v0.1 shipped a hand-rolled tool-use loop on top of the Messages API. That's
been replaced entirely by Claude Managed Agents,
Anthropic's managed agent runtime.
| Before (v0.1.x) | After (v0.3.0) |
|---|---|
| Hand-rolled tool-use loop in Go | Anthropic runs the loop |
Custom tools.go registry, schemas, per-tool Go code |
agent_toolset_20260401 — bash, web, files free |
agent_messages Timescale hypertable |
Anthropic stores event history server-side |
One Messages.Create call per agent turn |
Stream from /v1/sessions/:id/stream |
| ~400 lines of agent loop code | ~190 lines of session/stream/history glue |
What that means in practice:
- You don't define tools in Go anymore. Tools come from the Anthropic
toolset, MCP servers, or are added via the Anthropic Console. - Conversation history isn't persisted in your DB — it lives with Anthropic
and is fetched via the events list API on demand. - Bash, web search, web fetch, file read/write/glob/grep, and code execution
are all available to every agent automatically.
What's in the box
Backend (backend/)
cmd/
server/ Fiber API entrypoint (~150 lines)
migrate/ Goose runner: up / down / status / reset (~60 lines)
provision/ One-time: create Anthropic Agent + Environment (~70 lines)
internal/
agent/ service, store, handler, model — Managed Agents glue
apperrors/ Typed errors + Fiber ErrorHandler + UserID helper
auth/ Magic-link auth: service, middleware, handler
config/ All env vars in one place
db/migrations/ 00001_init.sql (the only schema file)
Fiber idioms throughout. Handlers return error; the centralized
apperrors.FiberHandler (wired via fiber.Config{ErrorHandler}) maps
typed errors to JSON responses. No apperrors.Handle(c, err) wrapping.
DRY persistence helpers. scanSession + sessionFields const in
agent/store.go; scanUser + selectUserBy(column, value) in
auth/service.go. Each user/session scan and field list lives in
exactly one place.
Rate limiting on /run scoped per authenticated user (10 req/60s by
default, env-configurable). Other endpoints unaffected.
Mobile + Web (mobile/)
Expo SDK 55. One codebase serves iOS, Android, and the web via
react-native-web.
(auth)/welcome.tsx— email → 6-digit OTP → JWT, with resend cooldown(app)/index.tsx— sessions list with pull-to-refresh, swipe to delete(app)/chat/[id].tsx— streaming chat, renderstool_useand
tool_resultblocks inline as they arriveservices/agent.ts— typed CRUD plus an async-generator that consumes
the SSE stream viaexpo/fetch
Token storage is config-driven via EXPO_PUBLIC_APP_SLUG so each client
fork uses its own secure-store key without conflicts.
Deploy (deploy/)
| Target | File | Notes |
|---|---|---|
| Fly.io | deploy/fly.toml |
One-command deploy with release_command migrations |
| Railway | deploy/railway.toml |
Push to GitHub → auto-deploy |
| GCP Cloud Run | deploy/cloudrun.md |
Step-by-step including Cloud Run Jobs for migrations |
| Kubernetes | deploy/k8s/ |
Namespace + secret + migrate Job + Deployment + Service + kustomization |
CI / CD
.github/workflows/ci.yml—go vet+go build+go test+tsc --noEmiton every push and PR.github/workflows/docker.yml— multi-arch image builds and pushes toghcr.io/teslashibe/agent-setupon tags andmain
API surface
Auth
| Method | Path | Description |
|---|---|---|
POST |
/auth/magic-link |
Send OTP + magic link to email |
POST |
/auth/verify |
Exchange OTP for JWT |
GET |
/auth/verify?token=… |
Magic-link click handler |
POST |
/auth/login |
Dev only — issue JWT directly |
Agent (require Authorization: Bearer <jwt>)
| Method | Path | Description |
|---|---|---|
GET |
/api/me |
Current user |
POST |
/api/agent/sessions |
Create a session (provisions Anthropic session under the hood) |
GET |
/api/agent/sessions |
List your sessions |
GET |
/api/agent/sessions/:id |
Get one session |
DELETE |
/api/agent/sessions/:id |
Delete a session |
GET |
/api/agent/sessions/:id/messages |
Replay full chat history (from Anthropic event list) |
POST |
/api/agent/sessions/:id/run |
Send a message; streams SSE of agent events |
SSE event shape
{ "type": "tool_use", "tool": "web_search", "tool_id": "sevt_…" }
{ "type": "tool_result", "tool_id": "sevt_…", "is_error": false }
{ "type": "text", "text": "Sure, here's what I found…" }
{ "type": "done" }
{ "type": "error", "error": "..." }Quickstart for a new client
# 1. Fork the template
gh repo create teslashibe/<client-name> --template teslashibe/agent-setup --private --clone
cd <client-name>
# 2. Bootstrap
make setup
# 3. Configure backend/.env
$EDITOR backend/.env
# ANTHROPIC_API_KEY=sk-ant-...
# JWT_SECRET=$(openssl rand -hex 32)
# AGENT_SYSTEM_PROMPT="You are <Client>'s expert..."
# 4. Provision the client's Anthropic Agent
make managed-agents-provision
# paste ANTHROPIC_AGENT_ID and ANTHROPIC_ENVIRONMENT_ID into backend/.env
# 5. Brand the mobile app (mobile/app.config.ts, mobile/.env.example,
# mobile/tailwind.config.js)
# 6. Run locally
make dev-all # API on :8080, Expo Web on :8081
# 7. Deploy (Fly.io example)
fly launch
fly secrets set \
ANTHROPIC_API_KEY=... \
ANTHROPIC_AGENT_ID=... \
ANTHROPIC_ENVIRONMENT_ID=... \
JWT_SECRET=... \
RESEND_API_KEY=... \
DATABASE_URL=...
fly deploySee README.md for the full step-by-step.
Refactor history (this release supersedes)
This release captures the entire arc since v0.1.0:
- v0.1.0 — Initial release: Fiber + Goose + TimescaleDB + Expo + hand-rolled Messages API tool-use loop
- v0.1.1 — Dockerfile fixed to match local Go toolchain
- v0.1.2 — End-to-end tested live against Anthropic API
- v0.1.3 — Per-user rate limiting on
/run; backlog issues filed for auto-title, delete session, EAS build - v0.2.0 — Migrated to Claude Managed Agents; deleted hand-rolled tool loop and
agent_messagestable; closed auto-title and delete-session issues - v0.2.1 — Removed 4 packages (
bootstrap/,db/db.go,httputil/,auth/model.go); 6 migrations consolidated into 1 - v0.2.2 — Idiomatic Fiber refactor: handlers return
error, centralizedErrorHandler, DRY scan helpers - v0.3.0 (this release) — Documentation rewrite focused on the per-client deployment workflow
The codebase is now ~1,150 lines of Go for a complete Claude agent product
with magic-link auth, sessions, streaming, history, rate limiting, and four
cloud deploy targets.
Known limitations
- EAS build config not yet included — see #4. For now, Expo Web + dev-server
npm run startcover all needs short of App Store / Play Store submission. - Email delivery in dev mode prints to logs — set
RESEND_API_KEYin production or no users will receive their OTP. - Anthropic Managed Agents is in beta (
managed-agents-2026-04-01header). Anthropic notes "behaviors may be refined between releases." We pin the SDK version ingo.modand verify each upgrade.
What we explicitly chose NOT to do
- No monorepo or workspaces — adds tooling complexity for two apps
- No git submodules — annoying and we'd regret them
- No premature package extraction —
magiclink-auth-gois the only shared lib until a real second consumer needs more - No custom MCP server wrapper — clients can wire MCP via the Anthropic Agent config
- No image / file upload pipeline — add per-client when needed; the Managed Agent already has file ops in its container
Credits
Built on Claude Managed Agents,
anthropic-sdk-go,
Fiber,
Goose,
TimescaleDB,
Expo,
NativeWind,
and magiclink-auth-go.
v0.2.2 — Idiomatic refactor
Pure refactor — no behaviour change, just cleaner Go.
What changed
Fiber idioms
- All handlers now return
error. The centralizedapperrors.FiberHandler(wired viafiber.Config{ErrorHandler}) maps*apperrors.Errorto JSON automatically. apperrors.Handle()deleted. ~25 lines ofreturn apperrors.Handle(c, err)boilerplate gone.apperrors.UserID(c) string— the auth middleware guarantees the value is set, so this returns a string instead of(string, error). Eliminates 4 lines per handler.
DRY
agent/store.go:scanSession+sessionFieldsconst. The 6-field column list now lives in exactly one place.auth/service.go:scanUser+selectUserBy(column, value)helpers.GetUserandGetByEmailare now one-line wrappers.agent/service.go History(): extractedappendAssistantclosure, replacing three copies ofif assistant == nil { ... }.agent/service.go Run(): extractedsendUserMessagehelper.
Naming / API surface
apperrors.AppError→apperrors.Error(idiomatic — package qualifier already says it).Handler.Mount(router, runLimiter ...fiber.Handler)→Handler.Mount(router, runLimiter fiber.Handler). Variadic was anti-pattern when only ever called with one arg.
Stats
1266 → 1154 lines (-9%).
All endpoints tested live against the Anthropic API in Docker:
- auth (good token / bad token / missing token)
- session create / list / get / delete (404 on missing, 204 on delete)
- live agent run with SSE streaming
- history reconstructed from Anthropic event list
- auto-title on first message
v0.2.1 — Simplified codebase
Housekeeping release after the Claude Managed Agents migration.
Changes
- 1 migration file (was 6) —
00001_init.sqlcontains the full current schema - 7 Go packages (was 11) — deleted
bootstrap/,db/db.go,httputil/,auth/model.go cmd/migratesimplified from 89 → 61 lines (removed step logic never used in practice)CurrentUserID/SetUserIDmoved intoapperrors— same HTTP concern, one importUserstruct merged intoauth/service.go— was a 12-line file for one struct- Pool creation inlined into
cmd/server/main.go— was a separate package for 10 lines
No functional changes. All tests pass.
v0.2.0 — Claude Managed Agents
Claude Managed Agents replaces the hand-rolled loop
The core agent runtime is now Claude Managed Agents. Instead of running our own tool-use loop against the Messages API, we delegate to Anthropic's managed infrastructure.
What this means in practice
| Before (v0.1.x) | After (v0.2.0) |
|---|---|
| Hand-rolled tool-use loop in Go | Anthropic runs the loop |
Custom tool registry in tools.go |
agent_toolset_20260401 (bash, web search, file ops free) |
agent_messages table in TimescaleDB |
Anthropic stores event history |
| One Messages API call per turn | Stream from /v1/sessions/:id/stream |
New setup step
After cloning, run once to create your Anthropic Agent + Environment:
make managed-agents-provision
# add ANTHROPIC_AGENT_ID + ANTHROPIC_ENVIRONMENT_ID to backend/.env
make upWhat Claude can now do out of the box
- Web search + fetch
- Bash execution in an Anthropic-managed cloud container
- File read/write/edit/glob/grep in the container
- All future Anthropic-built tools (MCP, etc.)
No tool definitions on your side. Extend by updating the Agent config or adding custom tools via the provision step.
API surface unchanged
The Fiber API, auth, sessions endpoints, and SSE streaming format are identical. The mobile app requires no changes.
Closes
Live test results
make managed-agents-provision→ Agent + Environment created in 2sPOST /api/agent/sessions→ our UUID + Anthropic session ID returnedPOST /api/agent/sessions/:id/run→ Claude calledweb_searchautonomously, streamedtool_use → tool_result → text → doneevents correctlyGET /api/agent/sessions/:id/messages→ history reconstructed from Anthropic event list API- Docker build, all 6 migrations,
go test ./...all clean