ARCHITECTURE.md

Shelley is an agentic loop with tool use. See https://sketch.dev/blog/agent-loop for an example of the idea.

When Shelley is started with "go run ./cmd/shelley" it starts a web server and opens a sqlite database, and users interact with the ui built in ui/. (The server itself is implemented in server/; cmd/shelley is a very thing shim.)

Components

ui/

TODO: A mobile-first UI. Infrastructure:

  • pnpm
  • Typescript
  • esbuild
  • ESLint and eslint-typescript
  • VueJS
  • Jest

db/

conversation(conversation_id, slug, user_initiated):

Represents a single conversation.

message(conversation_id, message_id, type (agent/user/tool), llm_data (json), user_data (json), usage (json))

Messages are visible in the UI and sent to the LLM as part of the conversation. There may be both user-visible and llm-visible representations of messages.

The database is sqlite. We use sqlc to define queries and schema.

TODOX: Subagent/tool conversations are done with user_initiated=false.

server/

The server serves the agent HTTP API and maintains active conversations. The HTTP API is:

/conversations?limit=5000&offset=0 /conversations?q=search_term

Returns conversations, either matching a query, or matching the paging requirements.

/conversation/

Returns all the messages within a conversation.

/conversation//stream

Returns all the messages within a conversation and uses SSE to wait for updates.

/conversation//chat (POST)

Injects a user message into the conversation

When a conversation is active (because it's had a message sent to it, or there are stream subscribers), a Conversation struct is instantiated from the data, and the server keeps a map of these. Each of these has a Loop struct to keep track of the interaction with the llm.

loop/

The core agentic loop.

claudetool/

Various tools for the LLM.

Other

Shelley talks to the LLMs using the llm/ library.

Logging happens with slog and the tint library.