Loading the notebook…
Loading the notebook…
Notebooks · Output, pipelines and memory · 10
Get typed, validated responses from LLMs. SHIPIT supports Pydantic models, JSON schemas, regex patterns, and markdown extraction — all as standalone parsers or as a one-parameter addition to agent.run().
Its imports and arguments are checked against shipit-agent 3.0. The outputs were saved when it was written, for an earlier release.
# Setup — add project root to path
from pathlib import Path
import sys
ROOT = (
Path.cwd().resolve().parent
if Path.cwd().name == "notebooks"
else Path.cwd().resolve()
)
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))LLMs often wrap JSON in markdown code fences, add explanatory prose, or produce slightly malformed output. JSONParser handles all of this automatically.
from shipit_agent.parsers import JSONParser, ParseError
parser = JSONParser()
# 1a. Clean JSON — works as expected
result = parser.parse('{"name": "Alice", "age": 30}')
print("Clean JSON:", result)
# 1b. JSON inside markdown code fence — automatically extracted
messy = """Here is the analysis:
```json
{"sentiment": "positive", "confidence": 0.95, "keywords": ["great", "love"]}
```
That's the result."""
result = parser.parse(messy)
print("\nFrom code fence:", result)
# 1c. JSON surrounded by prose — extracted automatically
prose = 'The answer is {"value": 42, "unit": "seconds"} and that is final.'
result = parser.parse(prose)
print("\nFrom prose:", result)
# 1d. Schema validation — check required keys
validated_parser = JSONParser(
schema={
"type": "object",
"properties": {"name": {"type": "string"}, "email": {"type": "string"}},
"required": ["name", "email"],
}
)
try:
validated_parser.parse('{"name": "Alice"}') # missing "email"
except ParseError as e:
print(f"\nValidation error: {e}")
# 1e. Format instructions for the LLM
print("\nFormat instructions:", validated_parser.get_format_instructions())Clean JSON: {'name': 'Alice', 'age': 30}
From code fence: {'sentiment': 'positive', 'confidence': 0.95, 'keywords': ['great', 'love']}
From prose: {'value': 42, 'unit': 'seconds'}
Validation error: Missing required key: email
Format instructions: Respond with valid JSON matching this schema:
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string"
}
},
"required": [
"name",
"email"
]
}Define a Pydantic model, and the parser returns a validated instance. Type safety, auto-completion, and runtime validation for free.
from pydantic import BaseModel
from shipit_agent.parsers import PydanticParser
# Define your data model
class MovieReview(BaseModel):
title: str
rating: float
summary: str
pros: list[str]
cons: list[str]
parser = PydanticParser(model=MovieReview)
# Parse LLM output into a typed instance
raw_json = """```json
{
"title": "The Matrix",
"rating": 9.5,
"summary": "A groundbreaking sci-fi film about reality and choice.",
"pros": ["Revolutionary visual effects", "Deep philosophical themes", "Iconic action scenes"],
"cons": ["Sequels didn't live up", "Some dated CGI"]
}
```"""
review = parser.parse(raw_json)
print(f"Type: {type(review).__name__}")
print(f"Title: {review.title}")
print(f"Rating: {review.rating}")
print(f"Pros: {review.pros}")
print(f"Cons: {review.cons}")
# Get the JSON schema for this model (useful for LLM prompting)
print(f"\nJSON Schema keys: {list(parser.get_json_schema()['properties'].keys())}")Type: MovieReview Title: The Matrix Rating: 9.5 Pros: ['Revolutionary visual effects', 'Deep philosophical themes', 'Iconic action scenes'] Cons: ["Sequels didn't live up", 'Some dated CGI'] JSON Schema keys: ['title', 'rating', 'summary', 'pros', 'cons']
Pull structured data from free-form text using regex. Great for scores, dates, emails, IDs, etc.
from shipit_agent.parsers import RegexParser
# Extract a score
score_parser = RegexParser(pattern=r"Score:\s*(\d+)/10", output_keys=["score"])
result = score_parser.parse(
"After careful review, the movie gets a Score: 8/10. Highly recommended."
)
print("Score:", result)
# Extract email components
email_parser = RegexParser(
pattern=r"(\w+)@(\w+)\.(\w+)", output_keys=["user", "domain", "tld"]
)
result = email_parser.parse("Please contact [email] for help.")
print("Email parts:", result)
# Extract a date
date_parser = RegexParser(
pattern=r"(\d{4})-(\d{2})-(\d{2})", output_keys=["year", "month", "day"]
)
result = date_parser.parse("The release date is 2026-04-10.")
print("Date:", result)
# Extract version
ver_parser = RegexParser(
pattern=r"v(\d+)\.(\d+)\.(\d+)", output_keys=["major", "minor", "patch"]
)
result = ver_parser.parse("Updated to v1.0.2 today")
print("Version:", result)Score: {'score': '8'}
Email parts: {'user': 'support', 'domain': 'shipit', 'tld': 'dev'}
Date: {'year': '2026', 'month': '04', 'day': '10'}
Version: {'major': '1', 'minor': '0', 'patch': '2'}LLMs love markdown. Extract code blocks, headings, and lists from markdown-formatted responses.
from shipit_agent.parsers import MarkdownParser
parser = MarkdownParser()
markdown_text = """# Quarterly Report
## Key Metrics
- Revenue: $2.4M (up 15%)
- Active users: 50,000
- Churn rate: 2.1%
## Code Example
```python
import pandas as pd
df = pd.read_csv("sales_q4.csv")
summary = df.groupby("region").sum()
print(summary)
```
## SQL Query
```sql
SELECT region, SUM(revenue) FROM sales WHERE quarter = 'Q4' GROUP BY region;
```
## Next Steps
- Launch marketing campaign
- Hire 3 engineers
- Ship v2.0 by end of Q1
"""
result = parser.parse(markdown_text)
print("=== HEADINGS ===")
for h in result.headings:
indent = " " * (int(h["level"]) - 1)
print(f"{indent}H{h['level']}: {h['text']}")
print("\n=== CODE BLOCKS ===")
for block in result.code_blocks:
print(f"[{block['language']}]")
print(f" {block['code'][:80]}...")
print("\n=== LIST ITEMS ===")
for item in result.lists:
print(f" - {item}")=== HEADINGS ===
H1: Quarterly Report
H2: Key Metrics
H2: Code Example
H2: SQL Query
H2: Next Steps
=== CODE BLOCKS ===
[python]
import pandas as pd
df = pd.read_csv("sales_q4.csv")
summary = df.groupby("regio...
[sql]
SELECT region, SUM(revenue) FROM sales WHERE quarter = 'Q4' GROUP BY region;...
=== LIST ITEMS ===
- Revenue: $2.4M (up 15%)
- Active users: 50,000
- Churn rate: 2.1%
- Launch marketing campaign
- Hire 3 engineers
- Ship v2.0 by end of Q1The killer feature: add output_schema to agent.run() and get typed, validated responses. Works with Pydantic models or raw JSON schema dicts.
from pydantic import BaseModel
from shipit_agent import Agent
from examples.run_multi_tool_agent import build_llm_from_env
from IPython.display import display, Markdown# --- 5a. Structured output with Pydantic model ---
class SentimentAnalysis(BaseModel):
sentiment: str # "positive", "negative", "neutral"
confidence: float # 0.0 to 1.0
key_phrases: list[str]
explanation: str
llm = build_llm_from_env("bedrock")
agent = Agent(llm=llm, name="structured-demo")
result = agent.run(
"Analyze the sentiment of: 'SHIPIT Agent is the best framework I have ever used! So clean and powerful.'",
output_schema=SentimentAnalysis,
)
if result.parsed:
analysis = result.parsed
print(f"Type: {type(analysis).__name__}")
print(f"Sentiment: {analysis.sentiment}")
print(f"Confidence: {analysis.confidence}")
print(f"Phrases: {analysis.key_phrases}")
print(f"Why: {analysis.explanation}")
else:
print("Raw output (parsing failed):")
display(Markdown(result.output))Type: SentimentAnalysis Sentiment: positive Confidence: 0.99 Phrases: ['best framework', 'clean and powerful'] Why: The statement uses strong positive language, praising the SHIPIT Agent as 'the best framework' and describing it as 'clean and powerful'. These superlatives and favorable adjectives clearly indicate a positive sentiment with high confidence.
# --- 5b. Structured output with raw JSON schema (no Pydantic needed) ---
result = agent.run(
"List the top 3 Python web frameworks with their key features.",
output_schema={
"type": "object",
"properties": {
"frameworks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"key_feature": {"type": "string"},
"stars": {"type": "string"},
},
},
},
},
"required": ["frameworks"],
},
)
if result.parsed:
for fw in result.parsed["frameworks"]:
print(f" {fw.get('name', '?'):15s} — {fw.get('key_feature', '?')}")
else:
print("Raw:", result.output[:200])Raw:
print("\n=== AGENT RESULT SUMMARY ===")
print("Parsed available :", result.parsed is not None)
print("Output available :", bool(result.output))
print("Messages count :", len(result.messages) if result.messages else 0)
print("Events count :", len(result.events) if result.events else 0)
print("Tool results :", len(result.tool_results) if result.tool_results else 0)=== AGENT RESULT SUMMARY === Parsed available : False Output available : False Messages count : 2 Events count : 5 Tool results : 0
print(result.parsed) # likely None
print(result.output) # check if JSON is here
print(result.messages) # check last messageNone [Message(role='system', content="You are Shipit, a capable general-purpose agent runtime.\n\nCore behavior:\n- Be accurate, direct, and execution-oriented.\n- Solve the user's task end-to-end when possible instead of stopping at analysis.\n- Use tools when they materially improve correctness, freshness, or efficiency.\n- Prefer structured evidence over guesses.\n\nTool behavior:\n- Read tool descriptions and tool prompts carefully before calling them.\n- Use the smallest correct tool for the job.\n- When a task is complex, plan before acting.\n- When information may be outdated, prefer web and… (1,077 more characters)