106 lines
4.6 KiB
Markdown
106 lines
4.6 KiB
Markdown
---
|
|
name: workflow
|
|
description: Create a marimo notebook for data analysis. Use when the request involves analysis over time periods, large data volumes, or when the user asks to "create a workflow".
|
|
disable-model-invocation: true
|
|
argument-hint: [topic]
|
|
---
|
|
|
|
# Workflow — Create a Marimo Notebook
|
|
|
|
## When to create a marimo notebook
|
|
|
|
Any request that involves **analysis over a period of time** (e.g., "meetings this month", "emails since January", "interaction trends") is likely to return a **large volume of data** — too much to process inline. In these cases, **always produce a marimo notebook** (a `.py` file following the patterns in the [notebook-patterns skill](.agents/skills/notebook-patterns/SKILL.md)).
|
|
|
|
Also create a notebook when the user asks to "create a workflow", "write a workflow", or "build an analysis".
|
|
|
|
If you're unsure whether a question is simple enough to answer directly or needs a notebook, **ask the user**.
|
|
|
|
## Always create a new workflow
|
|
|
|
When the user requests a workflow, **always create a new notebook file**. Do **not** modify or re-run an existing workflow unless the user explicitly asks you to (e.g., "update workflow 001", "fix the sentiment notebook", "re-run the existing analysis"). Each new request gets its own sequentially numbered file — even if it covers a similar topic to an earlier workflow.
|
|
|
|
## File naming and location
|
|
|
|
All notebooks go in the **`workflows/`** directory. Use a sequential number prefix so workflows stay ordered by creation:
|
|
|
|
```
|
|
workflows/<NNN>_<topic>_<scope>.py
|
|
```
|
|
|
|
- `<NNN>` — zero-padded sequence number (`001`, `002`, …). Look at existing files in `workflows/` to determine the next number.
|
|
- `<topic>` — what is being analyzed, in snake_case (e.g., `greyhaven_meetings`, `alice_emails`, `hiring_discussions`)
|
|
- `<scope>` — time range or qualifier (e.g., `january`, `q1_2026`, `last_30d`, `all_time`)
|
|
|
|
**Examples:**
|
|
|
|
```
|
|
workflows/001_greyhaven_meetings_january.py
|
|
workflows/002_alice_emails_q1_2026.py
|
|
workflows/003_hiring_discussions_last_30d.py
|
|
workflows/004_team_interaction_timeline_all_time.py
|
|
```
|
|
|
|
**Before creating a new workflow**, list existing files in `workflows/` to find the highest number and increment it.
|
|
|
|
## Plan before you implement
|
|
|
|
Before writing any notebook, **always propose a plan first** and get the user's approval. The plan should describe:
|
|
|
|
1. **Goal** — What question are we answering?
|
|
2. **Data sources** — Which entity types and API endpoints will be used?
|
|
3. **Algorithm / ETL steps** — Step-by-step description of the data pipeline: what gets fetched, how it's filtered, joined, or aggregated, and what the final output looks like.
|
|
4. **Output format** — Table columns, charts, or summary statistics the user will see.
|
|
|
|
Only proceed to implementation after the user confirms the plan.
|
|
|
|
## Validate before delivering
|
|
|
|
After writing or editing a notebook, **always run `uvx marimo check`** to verify it has no structural errors (duplicate variables, undefined names, branch expressions, etc.):
|
|
|
|
```bash
|
|
uvx marimo check workflows/NNN_topic_scope.py
|
|
```
|
|
|
|
A clean check (no output, exit code 0) means the notebook is valid. Fix any errors before delivering the notebook to the user.
|
|
|
|
## Steps
|
|
|
|
1. **Identify people** — Use ContactDB to resolve names/emails to `contact_id` values. For "me"/"my" questions, always start with `GET /api/contacts/me`.
|
|
2. **Find data** — Use DataIndex `GET /query` (exhaustive, paginated) or `POST /search` (semantic, ranked) with `contact_ids`, `entity_types`, `date_from`/`date_to`, `connector_ids` filters.
|
|
3. **Analyze** — For simple answers, process the API response directly. For complex multi-step analysis, build a marimo notebook (see the [notebook-patterns skill](.agents/skills/notebook-patterns/SKILL.md) for detailed patterns).
|
|
|
|
## Quick Example (Python)
|
|
|
|
> "Find all emails involving Alice since January"
|
|
|
|
```python
|
|
import httpx
|
|
|
|
CONTACTDB = "http://localhost:42000/contactdb-api"
|
|
DATAINDEX = "http://localhost:42000/dataindex/api/v1"
|
|
client = httpx.Client(timeout=30)
|
|
|
|
# 1. Resolve "Alice" to a contact_id
|
|
resp = client.get(f"{CONTACTDB}/api/contacts", params={"search": "Alice"})
|
|
alice_id = resp.json()["contacts"][0]["id"] # e.g. 42
|
|
|
|
# 2. Fetch all emails involving Alice (with pagination)
|
|
emails = []
|
|
offset = 0
|
|
while True:
|
|
resp = client.get(f"{DATAINDEX}/query", params={
|
|
"entity_types": "email",
|
|
"contact_ids": str(alice_id),
|
|
"date_from": "2025-01-01T00:00:00Z",
|
|
"limit": 50,
|
|
"offset": offset,
|
|
})
|
|
data = resp.json()
|
|
emails.extend(data["items"])
|
|
if offset + 50 >= data["total"]:
|
|
break
|
|
offset += 50
|
|
|
|
print(f"Found {len(emails)} emails involving Alice")
|
|
```
|