Loading the notebook…
Loading the notebook…
Notebooks · Specialist agents · 46
This notebook shows three things end-to-end:
Its imports and arguments are checked against shipit-agent 3.0. The outputs were saved when it was written, for an earlier release.
from pathlib import Path
# Resolve a notebook-local workspace whether this notebook is run
# from the repo root (`jupyter lab`) or from `notebooks/`.
# Put exports under notebooks/_dashboard_workspace either way.
def _find_notebooks_dir() -> Path:
cwd = Path.cwd().resolve()
if cwd.name == "notebooks":
return cwd
candidate = cwd / "notebooks"
return candidate if candidate.is_dir() else cwd
WORKSPACE = _find_notebooks_dir() / "_dashboard_workspace"
WORKSPACE.mkdir(parents=True, exist_ok=True)
print("workspace:", WORKSPACE)workspace: <repo>/notebooks/_dashboard_workspace
build_llm_from_settings resolves a provider from the provider key. All the settings listed below can alternatively be set via environment variables (SHIPIT_LLM_PROVIDER, SHIPIT_LITELLM_MODEL, SHIPIT_LITELLM_API_BASE, etc.) — whichever is more convenient for your deployment.
If your company already runs a LiteLLM proxy, point every shipit_agent Agent / Autopilot / crew at it with three fields:
| Field | What it is |
|---|---|
api_base | Your LiteLLM proxy URL, e.g. https://litellm.acme.com |
api_key | Bearer token your proxy accepts |
model | Whatever model alias the proxy routes — gpt-4o-mini, claude-sonnet-4-5, … |
The proxy handles credentials for upstream providers, rate-limiting, cost tracking, and routing — shipit_agent just speaks OpenAI-compatible HTTP to it.
# --- Option A: AWS Bedrock (default provider) -----------------
# Needs AWS credentials and AWS_REGION_NAME.
# llm = build_llm_from_settings({
# 'provider': 'bedrock',
# 'model': 'bedrock/openai.gpt-oss-120b-1:0',
# }, provider='bedrock')
# --- Option B: LiteLLM direct — any LiteLLM-supported model ---
# Examples: 'openai/gpt-4o-mini', 'anthropic/claude-sonnet-4-5',
# 'groq/llama-3.3-70b-versatile', 'ollama/llama3.1', etc.
# llm = build_llm_from_settings({
# 'provider': 'litellm',
# 'model': 'openai/gpt-4o-mini',
# 'api_key': os.environ.get('OPENAI_API_KEY'),
# }, provider='litellm')
# --- Option C: LiteLLM proxy (your URL + your key) -----------
# For companies running `litellm --config` as a central gateway.
# Two equivalent ways to wire it:
#
# C1. Factory path (declarative — good for env-driven configs):
# llm = build_llm_from_settings({
# 'provider': 'litellm',
# 'model': 'gpt-4o-mini', # alias your proxy routes
# 'api_base': 'https://litellm.my-company.internal',
# 'api_key': os.environ.get('MY_LITELLM_PROXY_TOKEN'),
# 'custom_llm_provider': 'openai', # proxy speaks OpenAI format
# }, provider='litellm')
#
# C2. Direct class (imperative — explicit about what gets constructed):
# from shipit_agent.llms import LiteLLMProxyChatLLM
# llm = LiteLLMProxyChatLLM(
# model='gpt-4o-mini',
# api_base='https://litellm.my-company.internal',
# api_key='sk-proxy-token',
# )
#
# Env-var shortcut: set SHIPIT_LITELLM_MODEL / SHIPIT_LITELLM_API_BASE /
# SHIPIT_LITELLM_API_KEY, then just call build_llm_from_settings(provider='litellm').
# For a notebook that runs without creds, use the deterministic echo model.
from shipit_agent.llms import SimpleEchoLLM
llm = SimpleEchoLLM()
print("llm:", type(llm).__name__)llm: ShipitLLM
The renderer is pure-Python and works standalone. You build a spec dict, call render_dashboard(spec), and get back a single self-contained HTML document (inline CSS, Chart.js via CDN only when a chart section is present).
from shipit_agent.tools.dashboard_render import render_dashboard
spec = {
"title": "Rahul — Complete Life Vision 2026–2035",
"subtitle": "Kundli + Hast Rekha · Venus dasha · April 2026",
"lang": "hi",
"sections": [
{
"type": "metrics",
"title": "Life Snapshot",
"columns": 4,
"items": [
{"label": "उम्र", "value": "30", "sub": "Best phase ahead"},
{"label": "दशा", "value": "शुक्र", "sub": "2043 तक"},
{"label": "Ventures", "value": "4", "sub": "ShipIt primary"},
{
"label": "साढ़ेसाती",
"value": "Peak",
"sub": "ends June 2027",
"color": "#ba7517",
},
],
},
{
"type": "line_chart",
"title": "Income growth 2026–2035",
"labels": [str(y) for y in range(2026, 2036)],
"values": [20, 35, 55, 70, 85, 95, 110, 140, 165, 190],
"color": "#185fa5",
},
{
"type": "bars",
"title": "Income sources",
"items": [
{"label": "Enterprise licensing", "pct": 88, "color": "#185fa5"},
{"label": "SaaS subscriptions", "pct": 75, "color": "#1d9e75"},
{"label": "Cloud hosted product", "pct": 65, "color": "#534ab7"},
{"label": "Courses / training", "pct": 50, "color": "#ba7517"},
{"label": "Consulting", "pct": 38, "color": "#888888"},
],
},
{
"type": "timeline",
"title": "Love life timeline",
"items": [
{
"period": "April 2026",
"head": "Internal transformation",
"desc": "Jupiter lagna. Aura improving. Prep phase.",
"dot_color": "#888888",
"tags": [{"text": "Prep", "color": "amber"}],
},
{
"period": "Jun–Jul 2026",
"head": "PEAK WINDOW",
"desc": "Significant connection. Friendship → romance.",
"dot_color": "#185fa5",
"tags": [
{"text": "Peak", "color": "blue"},
{"text": "She arrives", "color": "blue"},
],
},
{
"period": "2027–2028",
"head": "Marriage",
"desc": "Sadhesati khatam. Shaadi ki baat family tak.",
"dot_color": "#1d9e75",
"tags": [{"text": "Shaadi", "color": "green"}],
},
],
},
{
"type": "cards",
"title": "Future partner",
"columns": 2,
"cards": [
{
"title": "Physical appearance",
"rows": [
{
"strong": "Eyes:",
"text": "Deep, expressive, magnetic.",
"dot_color": "#185fa5",
},
{
"strong": "Height:",
"text": "5'4\" – 5'7\".",
"dot_color": "#185fa5",
},
{
"strong": "Style:",
"text": "Minimal, tasteful.",
"dot_color": "#185fa5",
},
],
},
{
"title": "Personality",
"rows": [
{
"strong": "First:",
"text": "Reserved, observant.",
"dot_color": "#1d9e75",
},
{
"strong": "Intelligence:",
"text": "High — matches yours.",
"dot_color": "#1d9e75",
},
{
"strong": "Love style:",
"text": "Acts of service.",
"dot_color": "#1d9e75",
},
],
},
],
},
{
"type": "lifestyle_grid",
"title": "Future lifestyle 2026–2035",
"items": [
{
"icon": "🏠",
"title": "Housing — 2027",
"desc": "Better Warsaw apartment.",
},
{
"icon": "🚗",
"title": "Car — 2027–28",
"desc": "Reliable, utility-focused.",
},
{"icon": "✈️", "title": "Travel", "desc": "Europe + international."},
{"icon": "💍", "title": "Marriage", "desc": "Meaningful ceremony."},
{
"icon": "👶",
"title": "Children — 2029–31",
"desc": "One child strong yoga.",
},
{"icon": "🌍", "title": "Global — 2030+", "desc": "Financial freedom."},
],
},
{
"type": "phases",
"title": "Life phases — year by year",
"items": [
{
"year": "2026 — Foundation",
"sub": "Venus–Venus → Venus–Sun",
"items": "ShipIt PH · Pro tier · First enterprise · Love May–Aug · 3–5x income",
"color": "#ba7517",
},
{
"year": "2027 — Transition",
"sub": "Sadhesati ends",
"items": "MRR stable · Marriage discussions · Team 3–5 · Intl clients",
"color": "#185fa5",
},
{
"year": "2028 — Milestone",
"sub": "Venus–Moon → Venus–Mars",
"items": "Marriage · 1000+ users · Property plan · Seed funding possible",
"color": "#1d9e75",
},
{
"year": "2030–33 — BREAKTHROUGH",
"sub": "Venus–Rahu · explosive",
"items": "Sudden rise · Acquisition offer · Major funding · ShipIt standard",
"color": "#d85a30",
},
],
},
{
"type": "bars",
"title": "Overall life score",
"items": [
{"label": "Career potential", "pct": 92, "color": "#185fa5"},
{"label": "Financial success", "pct": 88, "color": "#1d9e75"},
{"label": "Marriage happiness", "pct": 85, "color": "#534ab7"},
{"label": "Fame & recognition", "pct": 80, "color": "#ba7517"},
{"label": "Family happiness", "pct": 82, "color": "#1d9e75"},
{"label": "International reach", "pct": 75, "color": "#d85a30"},
],
},
{
"type": "verdict",
"title": "Final verdict",
"text": (
"Tum ek **self-made extraordinary journey** par ho. "
"June–August 2026 turning point hai. **2027–2028 shaadi, "
"2028–2030 financial freedom, 2030–2033 breakthrough.** "
"Tumhara best chapter abhi likhna baaki hai. 🌟"
),
},
],
}
html_doc = render_dashboard(spec)
out_path = WORKSPACE / "life_vision.html"
out_path.write_text(html_doc, encoding="utf-8")
print(f'wrote {out_path} — {len(html_doc):,} chars, {len(spec["sections"])} sections')wrote <repo>/notebooks/_dashboard_workspace/life_vision.html — 13,128 chars, 9 sections
The DashboardRenderTool exposes a JSON-schema function that any Agent can call. A model that's been handed this tool and a user prompt like "show me my finance future as a dashboard" will call it with the right spec shape.
With SimpleEchoLLM as the model the agent won't actually invoke the tool (echo models don't emit tool calls), but the construction still verifies the wiring. Swap to a real LLM above to see it call render_dashboard on its own.
from shipit_agent import Agent
from shipit_agent.tools.dashboard_render import DashboardRenderTool
dash_tool = DashboardRenderTool(workspace_root=WORKSPACE)
agent = Agent(
llm=llm,
prompt=(
"You are a life-planning assistant. When the user asks for a "
"visual dashboard, call render_dashboard with a well-structured spec."
),
tools=[dash_tool],
max_iterations=4,
name="life-dashboard-agent",
)
print(f"tools available: {[t.name for t in agent.tools]}")tools available: ['render_dashboard']
# Directly call the tool the way an LLM would — a round-trip through
# the ToolContext / ToolOutput layer mirrors exactly what an Agent does
# when its model emits a tool call.
from shipit_agent.tools.base import ToolContext
out = dash_tool.run(
ToolContext(prompt="demo", state={"artifact_workspace_root": str(WORKSPACE)}),
title="Finance One-Pager — FY26",
subtitle="Dashboard rendered via the agent tool path",
lang="en",
sections=[
{
"type": "metrics",
"title": "Q2 KPIs",
"columns": 3,
"items": [
{"label": "MRR", "value": "$12.4k", "sub": "+22% QoQ"},
{"label": "CAC", "value": "$89", "sub": "-8%"},
{"label": "LTV", "value": "$720", "sub": "payback 4.2mo"},
],
},
{
"type": "line_chart",
"title": "Revenue 2025–2026",
"labels": ["Q1-25", "Q2-25", "Q3-25", "Q4-25", "Q1-26", "Q2-26"],
"values": [4.2, 5.8, 7.5, 9.1, 10.2, 12.4],
"color": "#1d9e75",
},
{
"type": "verdict",
"title": "Takeaway",
"text": "Solid **2.5x YoY**. Focus Q3 on **retention**, not new acquisition.",
},
],
export=True,
)
print(out.text)
print("path:", out.metadata.get("path"))Dashboard rendered: finance-one-pager-fy26.html (3 sections, 6,078 chars). path: <repo>/notebooks/_dashboard_workspace/finance-one-pager-fy26.html
The tool returns the page itself too, so a notebook can show it right here:
from IPython.display import HTML
HTML(Path(out.metadata["path"]).read_text())ArtifactCollector.ingest_tool_metadata understands the same {'artifact': True, 'kind', 'name', 'content'} envelope the tool emits — so an Autopilot run wired with artifacts=True captures the rendered HTML without any integration code.
from shipit_agent.autopilot import ArtifactCollector
collector = ArtifactCollector()
collector.ingest_tool_metadata(out.metadata, iteration=1)
for a in collector.all():
print(f"{a.kind:<6} {a.name:<30} {len(a.content):>6,} chars")file finance-one-pager-fy26.html 6,078 chars
Autopilot(..., goal=Goal('Build a finance dashboard'), tools=[DashboardRenderTool(), ...], artifacts=True) for a long-running job that produces a dashboard at the end.model= works with LiteLLMChatLLM.litellm --config as a proxy and point every agent at it via LiteLLMProxyChatLLM (or provider='litellm' with api_base set).