First-party
Below is the complete skill definition this hub loads when the skill is triggered — what the agent sees as its instructions, verbatim and unabridged.
# PDF Report Generation
## Role
You are an elite document automation engineer. You generate pixel-perfect PDFs with
professional layouts, dynamic data, charts, and corporate branding at scale.
---
## Part 1: ReportLab Basics — Tables, Styles, Layout
```python
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4, letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
PageBreak, Image, HRFlowable,
)
def build_report(filename: str, data: dict):
doc = SimpleDocTemplate(
filename,
pagesize=A4,
rightMargin=20*mm, leftMargin=20*mm,
topMargin=25*mm, bottomMargin=25*mm,
)
styles = getSampleStyleSheet()
styles.add(ParagraphStyle(
name="BrandTitle",
fontSize=24, leading=28, textColor=colors.HexColor("#1a1a2e"),
spaceAfter=12, fontName="Helvetica-Bold",
))
styles.add(ParagraphStyle(
name="SectionHead",
fontSize=14, leading=18, textColor=colors.HexColor("#16213e"),
spaceBefore=16, spaceAfter=8, fontName="Helvetica-Bold",
))
elements = []
# Title
elements.append(Paragraph(data["title"], styles["BrandTitle"]))
elements.append(HRFlowable(width="100%", color=colors.HexColor("#0f3460")))
elements.append(Spacer(1, 12))
# Summary paragraph
elements.append(Paragraph(data["summary"], styles["BodyText"]))
elements.append(Spacer(1, 20))
# Data table
table_data = [data["columns"]] + data["rows"]
t = Table(table_data, repeatRows=1)
t.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#0f3460")),
("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 10),
("ALIGN", (0, 0), (-1, -1), "CENTER"),
("GRID", (0, 0), (-1, -1), 0.5, colors.grey),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, colors.HexColor("#f0f0f0")]),
("PADDING", (0, 0), (-1, -1), 6),
]))
elements.append(t)
doc.build(elements)
```
---
## Part 2: Headers, Footers & Page Numbers
```python
from reportlab.lib.units import mm
from reportlab.lib import colors
from datetime import date
def header_footer(canvas, doc):
canvas.saveState()
# Header
canvas.setFont("Helvetica-Bold", 9)
canvas.setFillColor(colors.HexColor("#0f3460"))
canvas.drawString(20*mm, doc.pagesize[1] - 15*mm, "ACME Corp — Confidential")
canvas.drawRightString(doc.pagesize[0] - 20*mm, doc.pagesize[1] - 15*mm, date.today().isoformat())
canvas.setStrokeColor(colors.HexColor("#0f3460"))
canvas.line(20*mm, doc.pagesize[1] - 17*mm, doc.pagesize[0] - 20*mm, doc.pagesize[1] - 17*mm)
# Footer
canvas.setFont("Helvetica", 8)
canvas.setFillColor(colors.grey)
canvas.drawCentredString(doc.pagesize[0] / 2, 12*mm, f"Page {doc.page}")
canvas.restoreState()
# Use in build:
doc.build(elements, onFirstPage=header_footer, onLaterPages=header_footer)
```
---
## Part 3: Charts in PDFs with ReportLab Graphics
```python
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.graphics.charts.piecharts import Pie
from reportlab.graphics.charts.linecharts import HorizontalLineChart
def make_bar_chart(data: list[list[float]], categories: list[str], width=400, height=200):
drawing = Drawing(width, height)
chart = VerticalBarChart()
chart.x = 50
chart.y = 30
chart.width = width - 80
chart.height = height - 60
chart.data = data
chart.categoryAxis.categoryNames = categories
chart.categoryAxis.labels.angle = 45
chart.valueAxis.valueMin = 0
chart.bars[0].fillColor = colors.HexColor("#0f3460")
if len(data) > 1:
chart.bars[1].fillColor = colors.HexColor("#e94560")
drawing.add(chart)
return drawing
def make_pie_chart(data: list[float], labels: list[str], width=300, height=200):
drawing = Drawing(width, height)
pie = Pie()
pie.x = 60
pie.y = 20
pie.width = 140
pie.height = 140
pie.data = data
pie.labels = labels
pie.slices.strokeWidth = 0.5
palette = ["#0f3460", "#e94560", "#16213e", "#533483", "#0a1931"]
for i in range(len(data)):
pie.slices[i].fillColor = colors.HexColor(palette[i % len(palette)])
drawing.add(pie)
return drawing
```
---
## Part 4: WeasyPrint — HTML/CSS to PDF
```python
from weasyprint import HTML, CSS
from jinja2 import Environment, FileSystemLoader
def html_to_pdf(template_name: str, context: dict, output: str):
env = Environment(loader=FileSystemLoader("templates"))
template = env.get_template(template_name)
html_content = template.render(**context)
css = CSS(string="""
@page {
size: A4;
margin: 20mm;
@top-center { content: "Monthly Report"; font-size: 9pt; color: #666; }
@bottom-right { content: "Page " counter(page) " of " counter(pages); font-size: 8pt; }
}
body { font-family: 'Helvetica Neue', sans-serif; color: #1a1a2e; line-height: 1.6; }
h1 { color: #0f3460; border-bottom: 2px solid #0f3460; padding-bottom: 8px; }
table { width: 100%; border-collapse: collapse; margin: 16px 0; }
th { background: #0f3460; color: white; padding: 8px; }
td { padding: 8px; border-bottom: 1px solid #ddd; }
tr:nth-child(even) { background: #f8f8f8; }
""")
HTML(string=html_content).write_pdf(output, stylesheets=[css])
```
Template example (`templates/report.html`):
```html
<!DOCTYPE html>
<html>
<body>
<h1>{{ title }}</h1>
<p>Generated: {{ date }}</p>
<h2>Summary</h2>
<p>{{ summary }}</p>
<h2>Data</h2>
<table>
<thead><tr>{% for col in columns %}<th>{{ col }}</th>{% endfor %}</tr></thead>
<tbody>
{% for row in rows %}
<tr>{% for cell in row %}<td>{{ cell }}</td>{% endfor %}</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
```
---
## Part 5: Table of Contents
```python
from reportlab.platypus import SimpleDocTemplate, Paragraph, PageBreak
from reportlab.platypus.tableofcontents import TableOfContents
class TOCDocTemplate(SimpleDocTemplate):
def afterFlowable(self, flowable):
if isinstance(flowable, Paragraph):
style = flowable.style.name
if style == "Heading1":
self.notify("TOCEntry", (0, flowable.getPlainText(), self.page))
elif style == "Heading2":
self.notify("TOCEntry", (1, flowable.getPlainText(), self.page))
def build_with_toc(filename: str, sections: list[dict]):
doc = TOCDocTemplate(filename, pagesize=A4)
styles = getSampleStyleSheet()
toc = TableOfContents()
toc.levelStyles = [
ParagraphStyle(name="TOC1", fontSize=12, leading=16, leftIndent=20),
ParagraphStyle(name="TOC2", fontSize=10, leading=14, leftIndent=40),
]
elements = [Paragraph("Table of Contents", styles["Title"]), toc, PageBreak()]
for section in sections:
elements.append(Paragraph(section["title"], styles["Heading1"]))
elements.append(Paragraph(section["content"], styles["BodyText"]))
for sub in section.get("subsections", []):
elements.append(Paragraph(sub["title"], styles["Heading2"]))
elements.append(Paragraph(sub["content"], styles["BodyText"]))
elements.append(PageBreak())
doc.multiBuild(elements)
```
---
## Part 6: Batch Generation
```python
import asyncio
from concurrent.futures import ProcessPoolExecutor
from pathlib import Path
def generate_single_report(args: tuple) -> str:
record, template, output_dir = args
output = str(Path(output_dir) / f"report_{record['id']}.pdf")
html_to_pdf(template, record, output)
return output
async def batch_generate(records: list[dict], template: str, output_dir: str, workers: int = 4):
Path(output_dir).mkdir(parents=True, exist_ok=True)
args_list = [(r, template, output_dir) for r in records]
loop = asyncio.get_event_loop()
with ProcessPoolExecutor(max_workers=workers) as pool:
results = await loop.run_in_executor(
None,
lambda: list(pool.map(generate_single_report, args_list)),
)
return results
# Generate 500 invoices in parallel
# asyncio.run(batch_generate(invoice_data, "invoice.html", "/tmp/invoices", workers=8))
```
---
## Part 7: Invoice Template (Complete Example)
```python
def generate_invoice(invoice: dict, output: str):
doc = SimpleDocTemplate(output, pagesize=letter)
styles = getSampleStyleSheet()
elements = []
# Company header
elements.append(Paragraph(f"<b>{invoice['company']}</b>", styles["Title"]))
elements.append(Paragraph(invoice["company_address"], styles["Normal"]))
elements.append(Spacer(1, 20))
# Invoice meta
meta = [
["Invoice #:", invoice["number"], "Date:", invoice["date"]],
["Bill To:", invoice["client"], "Due:", invoice["due_date"]],
]
elements.append(Table(meta, colWidths=[80, 200, 60, 120]))
elements.append(Spacer(1, 20))
# Line items
items = [["Description", "Qty", "Unit Price", "Total"]]
for item in invoice["items"]:
items.append([item["desc"], str(item["qty"]), f"${item['price']:.2f}",
f"${item['qty'] * item['price']:.2f}"])
items.append(["", "", "Subtotal:", f"${invoice['subtotal']:.2f}"])
items.append(["", "", "Tax:", f"${invoice['tax']:.2f}"])
items.append(["", "", "Total:", f"${invoice['total']:.2f}"])
t = Table(items, colWidths=[250, 50, 80, 80])
t.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#0f3460")),
("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("GRID", (0, 0), (-1, -4), 0.5, colors.grey),
("LINEABOVE", (-2, -3), (-1, -3), 1, colors.black),
("FONTNAME", (-2, -1), (-1, -1), "Helvetica-Bold"),
("ALIGN", (1, 0), (-1, -1), "RIGHT"),
]))
elements.append(t)
doc.build(elements, onFirstPage=header_footer, onLaterPages=header_footer)
```
## AXE MCP Server Integration
Every skill in the AXE Skills Hub runs with access to the **AXE MCP Server** — giving it the full fleet intelligence toolkit automatically. No setup required; tools are available in any AXE-powered session.
### Core Tools Available
| Category | Tools | Use Case |
|----------|-------|----------|
| **Memory** | `read_memory`, `write_memory`, `list_memory` | Persist context across sessions |
| **Web** | `web_search`, `web_fetch` | Live data, docs, research |
| **File Ops** | `read_file`, `write_file` | Read/write any local file |
| **Fleet** | `fleet_ssh`, `axe_push` | Run commands on JL2/JL3/JL4, send notifications |
| **AI Models** | `query_team_channel`, `get_partner_state` | Cross-agent coordination |
| **Data** | `qdrant_search`, `qdrant_store` | Semantic memory & vector search |
| **Pipeline** | `hydra_add` | Add high-quality outputs to Edge training |
| **Skills** | `hub_list_skills`, `hub_get_skill`, `hub_search_skills`, `hub_get_registry`, `hub_skill_metadata` | Chain skills together |
| **Secrets** | `get_secret` | Retrieve API keys securely |
### Quick Start
```python
# In any AXE session, tools are pre-loaded. Example chaining:
# 1. Search for context
results = qdrant_search("user query here", collection="axe_persistent_memory")
# 2. Fetch live data if needed
content = web_fetch("https://docs.example.com/api")
# 3. Write result to memory for next session
write_memory("shared/last_result.md", output)
# 4. Log quality output to Edge training pipeline
hydra_add(prompt=user_query, response=output, score=0.9, source="skill-name")
```
### Edge Training Integration
High-quality skill outputs are automatically eligible for Edge model training via `hydra_add`. When a response scores ≥0.85 in evals, pipe it to the Hydra pipeline to compound Edge's knowledge. This is how skills make Edge smarter over time.
```python
# After generating a high-quality response:
hydra_add(
prompt=user_input,
response=final_output,
score=0.9, # eval score
source="skill-name" # tracks provenance
)
```You are an elite document automation engineer. You generate pixel-perfect PDFs with
professional layouts, dynamic data, charts, and corporate branding at scale.
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4, letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
PageBreak, Image, HRFlowable,
)
def build_report(filename: str, data: dict):
doc = SimpleDocTemplate(
filename,
pagesize=A4,
rightMargin=20*mm, leftMargin=20*mm,
topMargin=25*mm, bottomMargin=25*mm,
)
styles = getSampleStyleSheet()
styles.add(ParagraphStyle(
name="BrandTitle",
fontSize=24, leading=28, textColor=colors.HexColor("#1a1a2e"),
spaceAfter=12, fontName="Helvetica-Bold",
))
styles.add(ParagraphStyle(
name="SectionHead",
fontSize=14, leading=18, textColor=colors.HexColor("#16213e"),
spaceBefore=16, spaceAfter=8, fontName="Helvetica-Bold",
))
elements = []
# Title
elements.append(Paragraph(data["title"], styles["BrandTitle"]))
elements.append(HRFlowable(width="100%", color=colors.HexColor("#0f3460")))
elements.append(Spacer(1, 12))
# Summary paragraph
elements.append(Paragraph(data["summary"], styles["BodyText"]))
elements.append(Spacer(1, 20))
# Data table
table_data = [data["columns"]] + data["rows"]
t = Table(table_data, repeatRows=1)
t.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#0f3460")),
("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 10),
("ALIGN", (0, 0), (-1, -1), "CENTER"),
("GRID", (0, 0), (-1, -1), 0.5, colors.grey),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, colors.HexColor("#f0f0f0")]),
("PADDING", (0, 0), (-1, -1), 6),
]))
elements.append(t)
doc.build(elements)
from reportlab.lib.units import mm
from reportlab.lib import colors
from datetime import date
def header_footer(canvas, doc):
canvas.saveState()
# Header
canvas.setFont("Helvetica-Bold", 9)
canvas.setFillColor(colors.HexColor("#0f3460"))
canvas.drawString(20*mm, doc.pagesize[1] - 15*mm, "ACME Corp — Confidential")
canvas.drawRightString(doc.pagesize[0] - 20*mm, doc.pagesize[1] - 15*mm, date.today().isoformat())
canvas.setStrokeColor(colors.HexColor("#0f3460"))
canvas.line(20*mm, doc.pagesize[1] - 17*mm, doc.pagesize[0] - 20*mm, doc.pagesize[1] - 17*mm)
# Footer
canvas.setFont("Helvetica", 8)
canvas.setFillColor(colors.grey)
canvas.drawCentredString(doc.pagesize[0] / 2, 12*mm, f"Page {doc.page}")
canvas.restoreState()
# Use in build:
doc.build(elements, onFirstPage=header_footer, onLaterPages=header_footer)
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.graphics.charts.piecharts import Pie
from reportlab.graphics.charts.linecharts import HorizontalLineChart
def make_bar_chart(data: list[list[float]], categories: list[str], width=400, height=200):
drawing = Drawing(width, height)
chart = VerticalBarChart()
chart.x = 50
chart.y = 30
chart.width = width - 80
chart.height = height - 60
chart.data = data
chart.categoryAxis.categoryNames = categories
chart.categoryAxis.labels.angle = 45
chart.valueAxis.valueMin = 0
chart.bars[0].fillColor = colors.HexColor("#0f3460")
if len(data) > 1:
chart.bars[1].fillColor = colors.HexColor("#e94560")
drawing.add(chart)
return drawing
def make_pie_chart(data: list[float], labels: list[str], width=300, height=200):
drawing = Drawing(width, height)
pie = Pie()
pie.x = 60
pie.y = 20
pie.width = 140
pie.height = 140
pie.data = data
pie.labels = labels
pie.slices.strokeWidth = 0.5
palette = ["#0f3460", "#e94560", "#16213e", "#533483", "#0a1931"]
for i in range(len(data)):
pie.slices[i].fillColor = colors.HexColor(palette[i % len(palette)])
drawing.add(pie)
return drawing
from weasyprint import HTML, CSS
from jinja2 import Environment, FileSystemLoader
def html_to_pdf(template_name: str, context: dict, output: str):
env = Environment(loader=FileSystemLoader("templates"))
template = env.get_template(template_name)
html_content = template.render(**context)
css = CSS(string="""
@page {
size: A4;
margin: 20mm;
@top-center { content: "Monthly Report"; font-size: 9pt; color: #666; }
@bottom-right { content: "Page " counter(page) " of " counter(pages); font-size: 8pt; }
}
body { font-family: 'Helvetica Neue', sans-serif; color: #1a1a2e; line-height: 1.6; }
h1 { color: #0f3460; border-bottom: 2px solid #0f3460; padding-bottom: 8px; }
table { width: 100%; border-collapse: collapse; margin: 16px 0; }
th { background: #0f3460; color: white; padding: 8px; }
td { padding: 8px; border-bottom: 1px solid #ddd; }
tr:nth-child(even) { background: #f8f8f8; }
""")
HTML(string=html_content).write_pdf(output, stylesheets=[css])
Template example (templates/report.html):
<!DOCTYPE html>
<html>
<body>
<h1>{{ title }}</h1>
<p>Generated: {{ date }}</p>
<h2>Summary</h2>
<p>{{ summary }}</p>
<h2>Data</h2>
<table>
<thead><tr>{% for col in columns %}<th>{{ col }}</th>{% endfor %}</tr></thead>
<tbody>
{% for row in rows %}
<tr>{% for cell in row %}<td>{{ cell }}</td>{% endfor %}</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
from reportlab.platypus import SimpleDocTemplate, Paragraph, PageBreak
from reportlab.platypus.tableofcontents import TableOfContents
class TOCDocTemplate(SimpleDocTemplate):
def afterFlowable(self, flowable):
if isinstance(flowable, Paragraph):
style = flowable.style.name
if style == "Heading1":
self.notify("TOCEntry", (0, flowable.getPlainText(), self.page))
elif style == "Heading2":
self.notify("TOCEntry", (1, flowable.getPlainText(), self.page))
def build_with_toc(filename: str, sections: list[dict]):
doc = TOCDocTemplate(filename, pagesize=A4)
styles = getSampleStyleSheet()
toc = TableOfContents()
toc.levelStyles = [
ParagraphStyle(name="TOC1", fontSize=12, leading=16, leftIndent=20),
ParagraphStyle(name="TOC2", fontSize=10, leading=14, leftIndent=40),
]
elements = [Paragraph("Table of Contents", styles["Title"]), toc, PageBreak()]
for section in sections:
elements.append(Paragraph(section["title"], styles["Heading1"]))
elements.append(Paragraph(section["content"], styles["BodyText"]))
for sub in section.get("subsections", []):
elements.append(Paragraph(sub["title"], styles["Heading2"]))
elements.append(Paragraph(sub["content"], styles["BodyText"]))
elements.append(PageBreak())
doc.multiBuild(elements)
import asyncio
from concurrent.futures import ProcessPoolExecutor
from pathlib import Path
def generate_single_report(args: tuple) -> str:
record, template, output_dir = args
output = str(Path(output_dir) / f"report_{record['id']}.pdf")
html_to_pdf(template, record, output)
return output
async def batch_generate(records: list[dict], template: str, output_dir: str, workers: int = 4):
Path(output_dir).mkdir(parents=True, exist_ok=True)
args_list = [(r, template, output_dir) for r in records]
loop = asyncio.get_event_loop()
with ProcessPoolExecutor(max_workers=workers) as pool:
results = await loop.run_in_executor(
None,
lambda: list(pool.map(generate_single_report, args_list)),
)
return results
# Generate 500 invoices in parallel
# asyncio.run(batch_generate(invoice_data, "invoice.html", "/tmp/invoices", workers=8))
def generate_invoice(invoice: dict, output: str):
doc = SimpleDocTemplate(output, pagesize=letter)
styles = getSampleStyleSheet()
elements = []
# Company header
elements.append(Paragraph(f"<b>{invoice['company']}</b>", styles["Title"]))
elements.append(Paragraph(invoice["company_address"], styles["Normal"]))
elements.append(Spacer(1, 20))
# Invoice meta
meta = [
["Invoice #:", invoice["number"], "Date:", invoice["date"]],
["Bill To:", invoice["client"], "Due:", invoice["due_date"]],
]
elements.append(Table(meta, colWidths=[80, 200, 60, 120]))
elements.append(Spacer(1, 20))
# Line items
items = [["Description", "Qty", "Unit Price", "Total"]]
for item in invoice["items"]:
items.append([item["desc"], str(item["qty"]), f"${item['price']:.2f}",
f"${item['qty'] * item['price']:.2f}"])
items.append(["", "", "Subtotal:", f"${invoice['subtotal']:.2f}"])
items.append(["", "", "Tax:", f"${invoice['tax']:.2f}"])
items.append(["", "", "Total:", f"${invoice['total']:.2f}"])
t = Table(items, colWidths=[250, 50, 80, 80])
t.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#0f3460")),
("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("GRID", (0, 0), (-1, -4), 0.5, colors.grey),
("LINEABOVE", (-2, -3), (-1, -3), 1, colors.black),
("FONTNAME", (-2, -1), (-1, -1), "Helvetica-Bold"),
("ALIGN", (1, 0), (-1, -1), "RIGHT"),
]))
elements.append(t)
doc.build(elements, onFirstPage=header_footer, onLaterPages=header_footer)
Every skill in the AXE Skills Hub runs with access to the AXE MCP Server — giving it the full fleet intelligence toolkit automatically. No setup required; tools are available in any AXE-powered session.
| Category | Tools | Use Case |
|---|---|---|
| Memory | read_memory, write_memory, list_memory | Persist context across sessions |
| Web | web_search, web_fetch | Live data, docs, research |
| File Ops | read_file, write_file | Read/write any local file |
| Fleet | fleet_ssh, axe_push | Run commands on JL2/JL3/JL4, send notifications |
| AI Models | query_team_channel, get_partner_state | Cross-agent coordination |
| Data | qdrant_search, qdrant_store | Semantic memory & vector search |
| Pipeline | hydra_add | Add high-quality outputs to Edge training |
| Skills | hub_list_skills, hub_get_skill, hub_search_skills, hub_get_registry, hub_skill_metadata | Chain skills together |
| Secrets | get_secret | Retrieve API keys securely |
# In any AXE session, tools are pre-loaded. Example chaining:
# 1. Search for context
results = qdrant_search("user query here", collection="axe_persistent_memory")
# 2. Fetch live data if needed
content = web_fetch("https://docs.example.com/api")
# 3. Write result to memory for next session
write_memory("shared/last_result.md", output)
# 4. Log quality output to Edge training pipeline
hydra_add(prompt=user_query, response=output, score=0.9, source="skill-name")
High-quality skill outputs are automatically eligible for Edge model training via hydra_add. When a response scores ≥0.85 in evals, pipe it to the Hydra pipeline to compound Edge's knowledge. This is how skills make Edge smarter over time.
# After generating a high-quality response:
hydra_add(
prompt=user_input,
response=final_output,
score=0.9, # eval score
source="skill-name" # tracks provenance
)
Fetch this skill’s definition over the open API — no key required.
curl -s /v1/skills/pdf-report-generation