mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-07-18 21:21:11 +02:00
feat(skills): single-source skill system with markdown SKILL.md + include directive
Skills move out of packages/core/src/application/assistant/skills/*/skill.ts
(TS string constants) into apps/skills/<id>/SKILL.md (Agent Skills spec format
— YAML frontmatter + markdown body). One directory, one loader, one place to
look at every skill the agent can load.
Key change vs the old dev system: a `{{include:<skill-id>}}` directive lets one
skill transclude another. This removes the parallel TS constant for the
knowledge-note style guide — it now lives at apps/skills/knowledge-note-style/
(hidden from catalog) and is pulled into doc-collab + the live-note and
background-task agents via the resolver instead of via a TS import.
Infrastructure:
- packages/core/src/skills/ — types, skill-md-parser, FS-backed official repo,
SkillResolver with recursive {{include:<id>}} expansion + cycle detection
- packages/shared/src/skill.ts — SkillFrontmatter, SkillCatalogEntry,
ResolvedSkill schemas
- DI: officialSkillsRepo + skillResolver registered; registerSkillsDir helper
wires the path before any consumer resolves
- IPC: skills:list / skills:get (read-only) for the Settings UI
- Main: resolveSkillsDir picks Resources/skills (packaged) or repo apps/skills
(dev). forge.config.cjs ships apps/skills/ as extraResource.
Consumer refactor:
- buildCopilotInstructions: catalog markdown built from resolver.getCatalog()
- builtin-tools: loadSkill uses resolver, new listSkills tool
- background-tasks/agent + live-note/agent: now async builders that load
the knowledge-note-style skill content via resolver
- runtime.loadAgent: awaits the now-async builders
- Deleted: assistant/skills/ directory, knowledge-note-style.ts
UI:
- New SkillsSettings component (read-only list + detail view) wired into
Settings dialog as the "Skills" tab.
This commit is contained in:
parent
b01af12148
commit
9a308cb7a9
38 changed files with 1217 additions and 1204 deletions
131
apps/skills/composio-integration/SKILL.md
Normal file
131
apps/skills/composio-integration/SKILL.md
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
---
|
||||
name: composio-integration
|
||||
description: >-
|
||||
Interact with third-party services (Gmail, GitHub, Slack, LinkedIn, Notion, Jira, Google Sheets, etc.) via Composio. Search, connect, and execute tools.
|
||||
metadata:
|
||||
title: "Composio Integration"
|
||||
---
|
||||
|
||||
# Composio Integration
|
||||
|
||||
**Load this skill** when the user asks to interact with ANY third-party service — email, GitHub, Slack, LinkedIn, Notion, Jira, Google Sheets, calendar, etc. This skill provides the complete workflow for discovering, connecting, and executing Composio tools.
|
||||
|
||||
## Available Tools
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| **composio-list-toolkits** | List all available integrations and their connection status |
|
||||
| **composio-search-tools** | Search for tools by use case; returns slugs and input schemas |
|
||||
| **composio-execute-tool** | Execute a tool by slug with parameters |
|
||||
| **composio-connect-toolkit** | Connect a service via OAuth (opens browser) |
|
||||
|
||||
## Toolkit Slugs (exact values for toolkitSlug parameter)
|
||||
|
||||
| Service | Slug |
|
||||
|---------|------|
|
||||
| Gmail | `gmail` |
|
||||
| Google Calendar | `googlecalendar` |
|
||||
| Google Sheets | `googlesheets` |
|
||||
| Google Docs | `googledocs` |
|
||||
| Google Drive | `googledrive` |
|
||||
| Slack | `slack` |
|
||||
| GitHub | `github` |
|
||||
| Notion | `notion` |
|
||||
| Linear | `linear` |
|
||||
| Jira | `jira` |
|
||||
| Asana | `asana` |
|
||||
| Trello | `trello` |
|
||||
| HubSpot | `hubspot` |
|
||||
| Salesforce | `salesforce` |
|
||||
| LinkedIn | `linkedin` |
|
||||
| X (Twitter) | `twitter` |
|
||||
| Reddit | `reddit` |
|
||||
| Dropbox | `dropbox` |
|
||||
| OneDrive | `onedrive` |
|
||||
| Microsoft Outlook | `microsoft_outlook` |
|
||||
| Microsoft Teams | `microsoft_teams` |
|
||||
| Calendly | `calendly` |
|
||||
| Cal.com | `cal` |
|
||||
| Intercom | `intercom` |
|
||||
| Zendesk | `zendesk` |
|
||||
| Airtable | `airtable` |
|
||||
|
||||
**IMPORTANT:** Always use these exact slugs. Do NOT guess — e.g., Google Sheets is `googlesheets` (no underscore), not `google_sheets`.
|
||||
|
||||
## Critical: Check First, Connect Second
|
||||
|
||||
**BEFORE calling composio-connect-toolkit, ALWAYS check if the service is already connected.** The system prompt includes a "Currently connected" list. If the service is there, skip connecting and go straight to search + execute.
|
||||
|
||||
**Flow:**
|
||||
1. Check if the service is in the "Currently connected" list (in the system prompt above)
|
||||
2. If **connected** → go directly to step 4
|
||||
3. If **NOT connected** → call `composio-connect-toolkit` once, wait for user to authenticate, then continue
|
||||
4. Call `composio-search-tools` with SHORT keyword queries
|
||||
5. Read the `inputSchema` from results — note `required` fields
|
||||
6. Call `composio-execute-tool` with slug, toolkit, and all required arguments
|
||||
|
||||
**NEVER call composio-connect-toolkit for a service that's already connected.** This creates duplicate connect cards in the UI.
|
||||
|
||||
## Search Query Tips
|
||||
|
||||
Use **short keyword queries**, not full sentences:
|
||||
|
||||
| ✅ Good | ❌ Bad |
|
||||
|---------|--------|
|
||||
| "list issues" | "get all open issues for a GitHub repository" |
|
||||
| "send email" | "send an email to someone using Gmail" |
|
||||
| "get profile" | "fetch the authenticated user's profile details" |
|
||||
| "create spreadsheet" | "create a new Google Sheets spreadsheet with data" |
|
||||
|
||||
If the first search returns 0 results, try a different short query (e.g., "issues" instead of "list issues").
|
||||
|
||||
## Passing Arguments
|
||||
|
||||
**ALWAYS include the `arguments` field** when calling `composio-execute-tool`, even if the tool has no required parameters.
|
||||
|
||||
- Read the `inputSchema` from search results carefully
|
||||
- Extract user-provided values into the correct fields (e.g., "rowboatlabs/rowboat" → `owner: "rowboatlabs", repo: "rowboat"`)
|
||||
- For tools with empty `properties: {}`, pass `arguments: {}`
|
||||
- For tools with required fields, pass all of them
|
||||
|
||||
### Example: GitHub Issues
|
||||
|
||||
User says: "Get me the open issues on rowboatlabs/rowboat"
|
||||
|
||||
1. `composio-search-tools({ query: "list issues", toolkitSlug: "github" })`
|
||||
→ finds `GITHUB_ISSUES_LIST_FOR_REPO` with required: ["owner", "repo"]
|
||||
2. `composio-execute-tool({ toolSlug: "GITHUB_ISSUES_LIST_FOR_REPO", toolkitSlug: "github", arguments: { owner: "rowboatlabs", repo: "rowboat", state: "open", per_page: 100 } })`
|
||||
|
||||
### Example: Gmail Fetch
|
||||
|
||||
User says: "What's my latest email?"
|
||||
|
||||
1. `composio-search-tools({ query: "fetch emails", toolkitSlug: "gmail" })`
|
||||
→ finds `GMAIL_FETCH_EMAILS`
|
||||
2. `composio-execute-tool({ toolSlug: "GMAIL_FETCH_EMAILS", toolkitSlug: "gmail", arguments: { user_id: "me", max_results: 5 } })`
|
||||
|
||||
### Example: LinkedIn Profile (no-arg tool)
|
||||
|
||||
User says: "Get my LinkedIn profile"
|
||||
|
||||
1. `composio-search-tools({ query: "get profile", toolkitSlug: "linkedin" })`
|
||||
→ finds `LINKEDIN_GET_MY_INFO` with properties: {}
|
||||
2. `composio-execute-tool({ toolSlug: "LINKEDIN_GET_MY_INFO", toolkitSlug: "linkedin", arguments: {} })`
|
||||
|
||||
## Error Recovery
|
||||
|
||||
- **If a tool call fails** (missing fields, 500 error): Fix the arguments and retry IMMEDIATELY. Do NOT stop and narrate the error to the user.
|
||||
- **If search returns 0 results**: Try a different short query. If still 0, the tool may not exist for that service.
|
||||
- **If a tool requires connection**: Call `composio-connect-toolkit` once, then retry after connection.
|
||||
|
||||
## Multi-Part Requests
|
||||
|
||||
When the user says "connect X and then do Y" — complete BOTH parts in one turn:
|
||||
1. If X is already connected (check the connected list), skip to Y immediately
|
||||
2. If X needs connecting, connect it, then proceed to Y after authentication
|
||||
|
||||
## Confirmation Rules
|
||||
|
||||
- **Read-only actions** (fetch, list, get, search): Execute without asking
|
||||
- **Mutating actions** (send email, create issue, post, delete): Show the user what you're about to do and confirm before executing
|
||||
- **Connecting a toolkit**: Always safe — just do it when needed
|
||||
Loading…
Add table
Add a link
Reference in a new issue