Skip to content

feat: inline Anthropic managed agents into main Go app#4748

Open
supernandor wants to merge 11 commits into
mainfrom
feat/agents-inline
Open

feat: inline Anthropic managed agents into main Go app#4748
supernandor wants to merge 11 commits into
mainfrom
feat/agents-inline

Conversation

@supernandor
Copy link
Copy Markdown
Contributor

Summary

Replaces the external agent service with pkg/agents/ inline in the main Go app.

Before: Go app → internal gRPC → Python agent (or agent2) → AI provider
After: Go app → Anthropic Sessions API directly

Key changes

File Purpose
pkg/agents/client.go Anthropic Sessions API client
pkg/agents/store.go GORM session + message persistence
pkg/agents/stream.go SSE handler (polls Anthropic, streams to frontend)
pkg/agents/service.go Business logic (GetOrCreate, Resume, Delete)
pkg/public/agent_stream.go HTTP route with cookie auth
db/migrations/... agent_sessions + agent_messages tables

Design decisions

  • Single session per canvas/user — enforced by unique constraint
  • Messages stored in main DB — provider-agnostic history
  • Cookie auth on stream endpoint — no JWT token exchange needed
  • No separate service — no internal gRPC, no Docker container
  • SSE polling — 2s interval, 10min timeout, same event format frontend expects

Config

AGENT_ENABLED=yes
ANTHROPIC_API_KEY=...
ANTHROPIC_AGENT_ID=...
ANTHROPIC_ENVIRONMENT_ID=...

What's NOT in this PR (follow-up)

  • Frontend changes (minor — remove token from stream request, use relative URL)
  • Cleanup of agent/, agent2/, protos/private/agents.proto
  • Tests

Replaces the external agent service (Python/agent2) with pkg/agents/
directly in the main app:

- pkg/agents/client.go: Anthropic Sessions API client
- pkg/agents/store.go: GORM-based session + message persistence
- pkg/agents/stream.go: SSE handler (poll Anthropic, stream events)
- pkg/agents/service.go: Business logic (GetOrCreate, Resume, Delete)
- pkg/public/agent_stream.go: HTTP route with cookie auth
- DB migration: agent_sessions + agent_messages tables

Single session per canvas/user. Messages stored locally.
No separate service, no internal gRPC, no JWT token exchange.
Stream endpoint uses cookie auth like all other routes.
- Delete agent/ directory (Python/Pydantic AI agent service)
- Delete protos/private/agents.proto (internal gRPC)
- Remove agent container from docker-compose.dev.yml
- Remove AGENT_GRPC_URL config
- Frontend: don't require token (cookie auth), add credentials:include
- Add binaries to .gitignore
@supernandor supernandor force-pushed the feat/agents-inline branch from 20e73bf to 82e6990 Compare May 12, 2026 18:50
- anthropic-version: 2023-06-01 (not 2025-01-01)
- event type: user.message (not user_message)
- events endpoint needs ?beta=true
- Add integration test that validates full flow against live API
Gorilla mux PathPrefix('/api/v1/agents') was shadowing the more specific
HandleFunc for the stream endpoint. Register stream route first.
- Frontend: include X-Organization-Id header in stream fetch (was causing 400)
- Backend: better error messages with field names in 400 responses
- Backend: add logging to stream handler for debugging
- Tests: 11 unit tests for Client (request format, headers, errors)
  and StreamHandler (validation, SSE format, text extraction)
The logging middleware wraps ResponseWriter but didn't implement
http.Flusher, breaking SSE streaming. Added Flush() delegation.
- ListAgentChats now returns the existing session for the canvas/user
- ListAgentChatMessages loads messages by chat_id directly
- Frontend auto-selects the existing session on sidebar open
- Single session per canvas/user — always continues the conversation
Before sending a message, snapshot existing event IDs. When polling,
skip all pre-existing events so only the new turn's events are streamed
to the frontend.
When session goes idle, do one more ListEvents call to catch any
events that arrived between the status check and the event list.
Prevents missing the final agent.message in multi-tool-call turns.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant