Skills
What skills are
A skill is a saved, replayable artifact that AI Partner can reuse without re-reasoning from scratch. When a goal matches a skill, the executor runs the stored sequence directly — skipping the LLM reasoning step entirely.
Why it matters: the first time you ask for something, the agent takes 30–90 seconds to reason, plan, and execute. The second time, it runs 3–5× faster.
Two kinds (one library, one UI)
| Kind | What it is | Where it's captured | UI |
|---|---|---|---|
| Code skills | Parameterized Python / Node scripts with {{PLACEHOLDER}} substitutions. Reused for repeatable script work (stock fetches, CSV transforms, document generation). | SkillLearner after a successful goal that ran a script | Settings → Learned Skills (top section) |
| Browser interaction skills | Recorded CDP action sequences (navigate / fill / click / extract) with {{PLACEHOLDER}} substitutions. Reused for repeatable browser work (directory submissions, form fills, login flows). | T3SkillRecorder after a successful partner-mode goal that used browser tools | Settings → Learned Skills (Browser Interaction Skills section) |
Both kinds appear in the same Learned Skills sidebar item (GraduationCap icon). They share the same matching mechanism (hybrid semantic + keyword), the same versioning, the same success/failure tracking. The only difference is the artifact format and where they capture from.
Storage:
- Code skills:
learned_skillsSQLite table +workspace/skills/learned/*.py|*.jsfiles (the file copy is for human-inspection and version control — you can browse / edit / version-control these as plain files) - Browser interaction skills:
t3_browser_skillsSQLite table only (no file copy — the action sequence isn't meaningful as a flat file)
API:
GET /api/skills/learned— code skillsGET /api/skills/browser— browser interaction skillsDELETE /api/skills/learned/:nameandDELETE /api/skills/browser/:id— remove a skill
Auto-learned skills
After every successful goal, the executor runs SkillLearner:
- Examines the successful script
- Extracts parameterizable variables (
TICKER,COMPANY,FILENAME, etc.) and replaces them with{{PLACEHOLDER}}syntax - Computes an embedding of the skill's description
- Checks for near-duplicates in the skill library (cosine similarity > 0.9)
- If no duplicate: saves as a new skill
- If a better version: saves as
v2and marks the old one superseded
Example — auto-learned skill:
After running "Get the current price of RELIANCE.NS from Yahoo Finance", the skill saved looks like:
# Skill: fetch_stock_price (v1)
# Keywords: stock price, Yahoo Finance, NSE, ticker
import yfinance as yf
import os
ticker = os.environ.get('TICKER', '{{TICKER}}')
stock = yf.Ticker(ticker)
info = stock.fast_info
print(f"{ticker}: ₹{info.last_price:.2f} ({info.day_change_percent:+.1f}%)")
Next time you ask "What's the HDFC Bank share price?", the executor:
- Detects keyword match: "share price" →
fetch_stock_price - Checks embedding similarity: 0.91 (above 0.75 threshold)
- Runs the skill with
TICKER=HDFCBANK.NS - Returns the result in ~3 seconds
Browsing the skill library
Go to sidebar → Learned Skills:
┌──────────────────────────────────────────────────────────────────┐
│ Learned Skills [+ New] │
├──────────────────────────────────────────────────────────────────┤
│ fetch_stock_price Python v2 ⭐ 19/20 auto [View] [Test] │
│ github_trending Python v1 ⭐ 8/10 auto [View] [Test] │
│ competitor_research Python v2 ⭐ 5/6 auto [View] [Test] │
│ weekly_news_digest Python v1 ⭐ 3/4 auto [View] [Test] │
│ daily_portfolio_check Python v1 ⭐ 0/0 manual [View] [Test] │
└──────────────────────────────────────────────────────────────────┘
Click View to see the stored script template, keywords, version history, and match statistics.
Click Test to run the skill immediately with test parameters.
Writing a manual skill
You don't have to wait for a goal to succeed. Write a skill in advance and it's available immediately.
Go to Learned Skills → + New Skill.
Generate with AI (recommended starting point)
The modal has a Generate with AI panel (Wand icon, expands at the top of the form). Enter a description of what the skill should do — at least 10 characters — choose Python or Node.js, and click Suggest:
Description: Fetch the current stock price of any NSE ticker using yfinance
Runtime: Python
The AI returns a pre-filled draft: name, keywords, strategy hint, and a complete script template with {{PLACEHOLDERS}}. Review and edit before saving — nothing is saved until you click Save.
The generator runs a security scan on the draft before returning it. If the model produces code that matches a restricted pattern, the request is rejected with a reason message — rephrase and try again.
Manual authoring
- 1Fill in the skill metadataName: daily_portfolio_checkKeywords: portfolio, my stocks, stock prices, watchlist, check holdingsRuntime: Python (or Node.js)Tags: finance, stocks, daily
Keywords are what the executor matches against incoming goals. Be specific — "check stocks" is too broad; "check my portfolio stocks" matches more precisely.
- 2Write the strategy hint (important)
The Strategy Hint is 2–3 plain-English sentences describing the approach — what library to use, what sequence to follow, any key gotchas. This is NOT code. It's injected into the agent's context at iteration 1 when the skill is matched, so the agent starts knowing the plan instead of figuring it out from scratch.
Use yfinance to fetch ticker data. Always use the .fast_info property forspeed — it avoids a full .info call. Handle TickerNotFound exceptionsper ticker so one bad symbol doesn't abort the whole list.A skill without a strategy hint still works, but the agent starts cold and may take an extra iteration to pick the right approach.
- 3Write the script template
Use
{{PLACEHOLDER}}for any variable that should be substituted from the goal:import yfinance as yfimport os# TICKERS can be overridden by the goal; defaults to a sensible listtickers = os.environ.get('TICKERS', 'RELIANCE.NS,INFY.NS,TCS.NS,HDFC.NS').split(',')print("📈 Portfolio Check\n")for ticker in tickers:try:stock = yf.Ticker(ticker)info = stock.fast_infoemoji = "🟢" if info.day_change_percent >= 0 else "🔴"print(f"{emoji} {ticker}: ₹{info.last_price:.2f} ({info.day_change_percent:+.1f}%)")except Exception as e:print(f"⚠️ {ticker}: error ({e})")The script is scanned for restricted patterns (shell injection, network backdoors, filesystem escapes) before saving. Scripts that fail the scan are rejected with a reason.
- 4Save and test
Click Save. The skill is immediately active — the next goal that matches the keywords will use it.
Click Test to run it right now and verify the output.
Skill promotion to MCP tools
A skill that proves itself gets promoted to a first-class MCP tool:
- Threshold: ≥5 successful uses AND ≥80% success rate
- Effect: the skill becomes callable as a tool in any ReAct reasoning step — not just matched from the keyword library
✅ Skill "fetch_stock_price" promoted to MCP tool
Available as: fetch_stock_price
Visible in: Tool Marketplace → Learned Skills category
Promoted skills appear in the Tool Marketplace and can be called by any agent profile that has them in its tool whitelist.
Skill versioning
When the agent generates a solution that outperforms the existing skill, it saves a new version:
fetch_stock_price v1: 6 successes, 60% rate — superseded
fetch_stock_price v2: 19 successes, 95% rate — current ✓
Versions are never deleted — you can view the history and manually roll back if needed.
The matching pipeline
When a goal arrives, the executor runs this check before generating anything:
Goal: "What's the HDFC share price today?"
↓
1. Keyword scan
Goal tokens: ["HDFC", "share", "price", "today"]
Skill keywords: ["stock price", "Yahoo Finance", "ticker"]
Overlap score: 0.72
2. Embedding similarity
embed("HDFC share price today") vs embed("fetch_stock_price description")
Cosine similarity: 0.91
3. Combined score: 0.87 → above threshold (0.75)
→ Match: "fetch_stock_price" (v2)
→ Run stored script with TICKER=HDFCBANK.NS
If the combined score is below threshold, no match. The full ReAct loop runs, generates a solution, and — if it succeeds — that solution potentially becomes a new skill.
Sharing skills with the org (multi-user)
On multi-user deployments, skills are private by default — your learned skills are recalled only for your goals. To make a skill available to every member:
- Click the Share icon on the skill in Learned Skills → it gets a
pending reviewbadge. - An admin reviews the full template in Admin Console → Skill Governance. Approval re-runs the code security scan — a template with restricted patterns is auto-rejected.
- Once approved, the skill shows an
orgbadge and is recalled for every member's matching goals (alongside their own private skills). - A rejected request shows a
share rejectedbadge with the admin's reason on hover.
The flow is deliberately two-sided: nothing is shared without both the owner's request and an admin's approval. Admins can later deprecate an org skill, reverting it to the owner's private library. System seed skills (shipped with AI Partner) remain visible to everyone as before.
POST /api/skills/learned/:id/share # member: request org sharing
GET /api/admin/skills/pending # admin: review queue
POST /api/admin/skills/:id/approve|reject|deprecate
Tips for writing effective skills
Avoid single-word keywords like "stocks" or "email". Use 2–4 word phrases that describe the exact task: "fetch stock price", "check gmail inbox", "create excel report".
Put all variable values in os.environ.get('PARAM', 'default'). The executor automatically maps goal entities (ticker names, company names, file paths) to env vars.
Wrap each operation in try/except and print a meaningful error. The self-corrector can fix code errors, but unhandled exceptions with no output are harder to debug.
The executor reads the script's stdout as the result. Always print the output you want the agent to see — don't just compute silently.