feat: migrate to skills-based approach

This commit is contained in:
2026-02-19 11:36:32 -06:00
parent 42a9b5289f
commit eefac81e57
15 changed files with 2565 additions and 224 deletions

137
README.md
View File

@@ -1,90 +1,77 @@
# InternalAI Agent
# InternalAI Workspace
A documentation and pattern library that gives LLM agents the context they need to build data analysis workflows against Monadical's internal systems — ContactDB (people directory) and DataIndex (unified data from email, calendar, Zulip, meetings, documents).
Agent-assisted workspace for analyzing and tracking Monadical's internal data: meetings, emails, Zulip conversations, calendar events, documents, and git activity.
The goal is to use [opencode](https://opencode.ai) (or any LLM-powered coding tool) to iteratively create [marimo](https://marimo.io) notebook workflows that query and analyze company data.
## Skills
## Setup
Skills are agent instructions stored in `.agents/skills/`. They follow the [Agent Skills](https://agentskills.io) standard (same structure as `.claude/skills/`). Some are invoked by the user via `/name`, others are background knowledge the agent loads automatically when relevant.
1. Install [opencode](https://opencode.ai)
2. Make sure InternalAI is running locally (ContactDB + DataIndex accessible via http://localhost:42000)
3. Configure LiteLLM — add to `~/.config/opencode/config.json`:
### Task Skills (user-invoked)
```json
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"litellm": {
"npm": "@ai-sdk/openai-compatible",
"name": "Litellm",
"options": {
"baseURL": "https://litellm.app.monadical.io",
"apiKey": "xxxxx"
},
"models": {
"Kimi-K2.5-dev": {
"name": "Kimi-K2.5-dev"
}
}
}
}
}
```
These are workflows you trigger explicitly. The agent will not run them on its own.
Replace `xxxxx` with your actual LiteLLM API key.
| Skill | Invocation | Purpose |
|-------|-----------|---------|
| **project-init** | `/project-init [name]` | Set up a new project: create directory structure, discover data sources (Zulip streams, git repos, meeting rooms), write `datasources.md` and `background.md` skeleton. Stops before gathering data so you can review the sources. |
| **project-history** | `/project-history [name] [from] [to]` | Build the initial timeline for a project. Queries all datasources for a date range, creates week-by-week analysis files, builds the timeline index, and synthesizes the background. Requires `project-init` first. |
| **project-sync** | `/project-sync [name]` | Incremental update of a project timeline. Reads the last sync date from `sync-state.md`, fetches new data through today, creates new week files, and refreshes the timeline and background. |
| **checkout** | `/checkout` | Build a weekly review (Sunday through today). Gathers meetings, emails, Zulip conversations, and Gitea activity, then produces a structured checkout summary. |
| **workflow** | `/workflow [topic]` | Create a marimo notebook for data analysis. Use for any request involving analysis over time periods or large data volumes. |
4. **Set up your profile** — copy the example and fill in your name, role, and contact ID so the agent can personalize workflows:
### Reference Skills (agent-loaded automatically)
```bash
cp MYSELF.example.md MYSELF.md
```
These provide background knowledge the agent loads when relevant. They don't appear in the `/` menu.
5. **(Optional) LLM filtering in workflows** — if your workflows need to classify or score entities via an LLM, copy `.env.example` to `.env` and fill in your key:
| Skill | What the agent learns |
|-------|----------------------|
| **connectors** | Which data connectors exist and what entity types they produce (reflector, zulip, email, calendar, etc.) |
| **dataindex** | How to query the DataIndex REST API (`GET /query`, `POST /search`, `GET /entities/{id}`) |
| **contactdb** | How to resolve people to contact IDs via the ContactDB REST API |
| **company** | Monadical org structure, Zulip channel layout, communication tools, meeting/calendar relationships |
| **notebook-patterns** | Marimo notebook rules: cell scoping, async patterns, pagination helpers, analysis templates |
```bash
cp .env.example .env
```
## Project Tracking
The `workflows/lib` module provides an `llm_call` helper (using [mirascope](https://mirascope.io)) for structured LLM calls — see Pattern 5 in `docs/notebook-patterns.md`.
Project analysis files live in `projects/`. See [projects/README.md](projects/README.md) for the directory structure and categorization guidelines.
## Quickstart
1. Run `opencode` from the project root
2. Ask it to create a workflow, e.g.: *"Create a workflow that shows all meetings about Greyhaven in January"*
3. The agent reads `AGENTS.md`, proposes a plan, and generates a notebook like `workflows/001_greyhaven_meetings_january.py`
4. Run it: `uvx marimo edit workflows/001_greyhaven_meetings_january.py`
5. Iterate — review the output in marimo, go back to opencode and ask for refinements
## How AGENTS.md is Structured
`AGENTS.md` is the entry point that opencode reads automatically. It routes the agent to the right documentation:
| Topic | File |
|-------|------|
| Your identity, role, preferences | `MYSELF.md` (copy from `MYSELF.example.md`) |
| Company context, tools, connectors | `docs/company-context.md` |
| People, contacts, relationships | `docs/contactdb-api.md` |
| Querying emails, meetings, chats, docs | `docs/dataindex-api.md` |
| Connector-to-entity-type mappings | `docs/connectors-and-sources.md` |
| Notebook templates and patterns | `docs/notebook-patterns.md` |
It also includes API base URLs, a translation table mapping natural-language questions to API calls, and rules for when/how to create workflow notebooks.
## Project Structure
**Typical workflow:**
```
internalai-agent/
├── AGENTS.md # LLM agent routing guide (entry point)
├── MYSELF.example.md # User profile template (copy to MYSELF.md)
├── .env.example # LLM credentials template
├── docs/
│ ├── company-context.md # Monadical org, tools, key concepts
│ ├── contactdb-api.md # ContactDB REST API reference
│ ├── dataindex-api.md # DataIndex REST API reference
│ ├── connectors-and-sources.md # Connector → entity type mappings
│ └── notebook-patterns.md # Marimo notebook templates and patterns
└── workflows/
└── lib/ # Shared helpers for notebooks
├── __init__.py
└── llm.py # llm_call() — structured LLM calls via mirascope
/project-init myproject # 1. Discover sources, create skeleton
# Review datasources.md, adjust if needed
/project-history myproject 2025-06-01 2026-02-17 # 2. Backfill history
# ... time passes ...
/project-sync myproject # 3. Incremental update
```
Each project produces:
```
projects/{name}/
├── datasources.md # Where to find data (Zulip streams, git repos, meeting rooms)
├── background.md # Living doc: current status, team, architecture
├── sync-state.md # Tracks last sync date for incremental updates
└── timeline/
├── index.md # Navigation and milestones
└── {year-month}/
└── week-{n}.md # One week of history (write-once)
```
## Data Analysis Workflows
Analysis notebooks live in `workflows/`. Each is a marimo `.py` file.
```
/workflow meetings-with-alice # Creates workflows/NNN_meetings_with_alice.py
```
See the [workflow skill](.agents/skills/workflow/SKILL.md) for naming conventions and the [notebook-patterns skill](.agents/skills/notebook-patterns/SKILL.md) for marimo coding rules.
## Data Sources
All data flows through two APIs:
- **DataIndex** (`localhost:42000/dataindex/api/v1` direct, `http://caddy/dataindex/api/v1` via greywall sandbox) — unified query interface for all entity types
- **ContactDB** (`localhost:42000/contactdb-api` direct, `http://caddy/contactdb-api/` via greywall sandbox) — people directory, resolves names/emails to contact IDs
Connectors that feed DataIndex: `reflector` (meetings), `zulip` (chat), `mbsync_email` (email), `ics_calendar` (calendar), `hedgedoc` (documents), `browser_history` (web pages), `babelfish` (translations).