Loading the notebook…
Loading the notebook…
Notebooks · Teams, costs and notifications · 31
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
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))
from examples.run_multi_tool_agent import build_llm_from_env
llm = build_llm_from_env("bedrock")from shipit_agent import Agent, AgentHooks
MODEL_COSTS = {
"bedrock/openai.gpt-oss-120b-1:0'": {
"input": 0.15,
"output": 0.60,
}, # per 1M tokens
"gpt-4o": {"input": 2.50, "output": 10.00},
}
hooks = AgentHooks()
costs = {"total_usd": 0.0}
@hooks.on_after_llm
def track_cost(response):
model = response.metadata.get("model", "")
rates = MODEL_COSTS.get(model, {"input": 0, "output": 0})
prompt_cost = response.usage.get("prompt_tokens", 0) / 1_000_000 * rates["input"]
completion_cost = (
response.usage.get("completion_tokens", 0) / 1_000_000 * rates["output"]
)
costs["total_usd"] += prompt_cost + completion_cost
agent = Agent.with_builtins(
llm=llm,
hooks=hooks,
)
data = agent.run("Do something complex with multiple tool calls")
print(f"Total cost: ${costs['total_usd']:.4f}")Total cost: $0.0000
from shipit_agent import AsyncAgentRuntime
async def main():
runtime = AsyncAgentRuntime(
llm=llm,
prompt="You are a helpful assistant.",
)
state, response = await runtime.run("What is 2 + 2?")
print(response.content)from shipit_agent import FunctionTool, AgentHooks
def search_web(query: str) -> str:
return f"Results for: {query}"
def fetch_url(url: str) -> str:
return f"Content of {url}"
runtime = AsyncAgentRuntime(
llm=llm,
prompt="You are a research assistant.",
tools=[
FunctionTool.from_callable(search_web),
FunctionTool.from_callable(fetch_url),
],
parallel_tool_execution=True, # run tools concurrently
hooks=AgentHooks(), # attach hooks
context_window_tokens=128000, # enable context management
)
state, response = await runtime.run("Research quantum computing advances")stateRuntimeState(messages=[Message(role='system', content='You are a research assistant.\n\nAvailable tools:\n- search_web: Function tool for search_web\n Guidance: Call a direct Python function tool.\n\nUse this when:\n- a deterministic local function can solve the task directly\n- code-free execution is preferable to a heavier tool or model call\n\nRules:\n- pass only the needed arguments\n- prefer these tools for stable utility operations\n- fetch_url: Function tool for fetch_url\n Guidance: Call a direct Python function tool.\n\nUse this when:\n- a deterministic local function can solve the … (7,174 more characters)
for m in state.messages:
if m.role == "tool":
print(f"{m.name}: {m.content}")search_web: Results for: latest quantum computing advances 2025 2026 quantum supremacy error correction scaling search_web: Results for: IBM quantum roadmap 2025 2026 qubits fetch_url: Content of https://news.mit.edu/2025/quantum-computer-supremacy-100-qubits-0121 fetch_url: Content of https://news.mit.edu/2025/quantum-computer-supersupremacy-100-qubits-0121
def inspect_runtime_state(state):
print("\n=== FINAL OUTPUT ===")
final_payload = state.events[-1].payload if state.events else {}
print("content:", repr(final_payload.get("content", "")))
print("output:", repr(final_payload.get("output", "")))
print("\n=== TOOL RESULTS ===")
for r in getattr(state, "tool_results", []):
print(f"- {r.name}: {r.output}")
print("\n=== REASONING ===")
for e in getattr(state, "events", []):
if getattr(e, "type", None) == "reasoning_completed":
print("-", e.payload.get("content", ""))
print("\n=== MESSAGES ===")
for i, m in enumerate(getattr(state, "messages", [])):
print(f"\n[{i}] role={m.role}")
print("content:", repr(m.content))
print("name:", getattr(m, "name", None))
print("metadata:", m.metadata)def get_best_result(state):
if state.events:
final_payload = state.events[-1].payload
final = final_payload.get("content") or final_payload.get("output")
if final:
return final
reasoning = [
e.payload.get("content", "")
for e in state.events
if e.type == "reasoning_completed" and e.payload.get("content")
]
if reasoning:
return "\n\n".join(reasoning)
tool_outputs = [f"{r.name}: {r.output}" for r in state.tool_results]
return "\n".join(tool_outputs)inspect_runtime_state(state)=== FINAL OUTPUT ===
content: ''
output: ''
=== TOOL RESULTS ===
- search_web: Results for: latest quantum computing advances 2025 2026 quantum supremacy error correction scaling
- search_web: Results for: IBM quantum roadmap 2025 2026 qubits
- fetch_url: Content of https://news.mit.edu/2025/quantum-computer-supremacy-100-qubits-0121
- fetch_url: Content of https://news.mit.edu/2025/quantum-computer-supersupremacy-100-qubits-0121
=== REASONING ===
- The user wants to "Research quantum computing advances". Likely they want a summary of recent advances in quantum computing. We need to produce a research summary. Possibly include latest breakthroughs, hardware (e.g., superconducting qubits, trapped ions, photonic), algorithms, error correction, scaling, commercial developments. Should be up-to-date as of 2026 (knowledge cutoff 2024 but we can search web for latest). Use search_web to find recent news. Let's search.
- We need to gather recent advances up to 2026. Summarize key milestones: quantum supremacy demonstrations, error correction, hardware: superconducting qubits (Google, IBM, Rigetti), trapped ions (IonQ, Honeywell), photonic (PsiQuantum), neutral atoms (Pasqal, QuEra), topological qubits (Microsoft). Also software: quantum algorithms, quantum machine learning, variational algorithms, QAOA improvements, quantum error mitigation, quantum volume benchmarks. Also mention scaling of qubit counts: IBM's roadmap: 433 qubits 2025, 1,121 qubits 2026? Actually IBM announced 2025 2,000 qubits? Need verify… (37 more characters)
- We need research quantum computing advances. Need summarize latest developments up to 2026. Use web results. Let's open some.
- We need to fetch the page.
=== MESSAGES ===
[0] role=system
content: 'You are a research assistant.\n\nAvailable tools:\n- search_web: Function tool for search_web\n Guidance: Call a direct Python function tool.\n\nUse this when:\n- a deterministic local function can solve the task directly\n- code-free execution is preferable to a heavier tool or model call\n\nRules:\n- pass only the needed arguments\n- prefer these tools for stable utility operations\n- fetch_url: Function tool for fetch_url\n Guidance: Call a direct Python function tool.\n\nUse this when:\n- a deterministic local function can solve the task directly\n- code-free execution is prefe… (134 more characters)
name: None
metadata: {}
[1] role=user
content: 'Research quantum computing advances'
name: None
metadata: {}
[2] role=assistant
content: ''
name: None
metadata: {'model': 'bedrock/openai.gpt-oss-120b-1:0', 'provider': 'litellm', 'tool_calls': [{'id': 'call_1_1', 'name': 'search_web', 'arguments': {'query': 'latest quantum computing advances 2025 2026 quantum supremacy error correction scaling'}}]}
[3] role=tool
content: 'Results for: latest quantum computing advances 2025 2026 quantum supremacy error correction scaling'
name: search_web
metadata: {'tool_call_id': 'call_1_1'}
[4] role=assistant
content: ''
… 27 more linesget_best_result(state)'The user wants to "Research quantum computing advances". Likely they want a summary of recent advances in quantum computing. We need to produce a research summary. Possibly include latest breakthroughs, hardware (e.g., superconducting qubits, trapped ions, photonic), algorithms, error correction, scaling, commercial developments. Should be up-to-date as of 2026 (knowledge cutoff 2024 but we can search web for latest). Use search_web to find recent news. Let\'s search.\n\nWe need to gather recent advances up to 2026. Summarize key milestones: quantum supremacy demonstrations, error correction,… (675 more characters)
from shipit_agent import Agent, AgentHooks
hooks = AgentHooks()
@hooks.on_before_llm
def log_llm_call(messages, tools):
print(f"Calling LLM with {len(messages)} messages, {len(tools)} tools")
@hooks.on_after_llm
def track_tokens(response):
usage = response.usage
if usage:
print(f"Tokens: {usage.get('total_tokens', 0)}")
@hooks.on_before_tool
def log_tool_start(name, arguments):
print(f"Running {name}...")
@hooks.on_after_tool
def log_tool_end(name, result):
print(f"{name} returned {len(result.output)} chars")
agent = Agent.with_builtins(
llm=llm,
hooks=hooks,
)
result = agent.run("What is the weather in Tokyo?")Calling LLM with 2 messages, 32 tools Tokens: 12148 Running web_search... web_search returned 2102 chars Calling LLM with 4 messages, 32 tools
open_url: Playwright fetch failed for https://weather.com/weather/hourbyhour/l/a2d49e31992a3679724161c3a9029211ecefeda3e1da24489637a5685ded3fdf: It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead.
Tokens: 12967 Running open_url... open_url returned 4000 chars Calling LLM with 6 messages, 32 tools
open_url: Playwright fetch failed for https://wttr.in/Tokyo?format=3: It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead.
Tokens: 13767 Running open_url... open_url returned 14 chars Calling LLM with 8 messages, 32 tools
open_url: Playwright fetch failed for https://wttr.in/Tokyo?format=%l:+%c+%t+%w+%h: It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead.
Tokens: 13815 Running open_url... open_url returned 25 chars Calling LLM with 10 messages, 32 tools Tokens: 13901
hooks = AgentHooks()
hooks.before_llm.append(lambda msgs, tools: print("calling LLM"))total_cost = {"tokens": 0}
@hooks.on_after_llm
def accumulate(response):
total_cost["tokens"] += response.usage.get("total_tokens", 0)
agent.run("Do something complex")
print(f"Total tokens used: {total_cost['tokens']}")Calling LLM with 2 messages, 32 tools Tokens: 12394 Running ask_user... ask_user returned 427 chars Calling LLM with 4 messages, 32 tools Tokens: 12474 Total tokens used: 0
import time
last_call = {"time": 0.0}
@hooks.on_before_llm
def rate_limit(messages, tools):
elapsed = time.time() - last_call["time"]
if elapsed < 1.0:
time.sleep(1.0 - elapsed)
last_call["time"] = time.time()@hooks.on_after_tool
def filter_pii(name, result):
if "email" in result.output.lower():
print(f"Warning: {name} output may contain PII")BLOCKED_TOOLS = {"code_execution", "workspace_files"}
@hooks.on_before_tool
def block_dangerous_tools(name, arguments):
if name in BLOCKED_TOOLS:
raise PermissionError(f"Tool {name} is blocked by policy")from shipit_agent import Agent
agent = Agent.with_builtins(
llm=llm,
parallel_tool_execution=True, # run tools concurrently
)
# result = agent.run("Search for Python 3.13 release notes and today's weather in NYC")
for event in agent.stream(
"Search for Python 3.13 release notes and today's weather in NYC"
):
if event.type == "tool_called":
print(f"Tool called: {event.payload.get('arguments', {})}")
elif event.type == "tool_completed":
print(f"Tool done: {event.payload.get('output', '')[:200]}")
elif event.type == "reasoning_completed":
print(f"Reasoning: {event.payload.get('content', '')[:200]}")
elif event.type == "run_completed":
print(f"Final: {event.payload.get('content', '')[:500]}")
else:
print(f"[{event.type}] {event.message}")[run_started] Agent run started
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: The user wants two pieces of info: Python 3.13 release notes and today's weather in NYC.
We need to fetch up-to-date info. Use web_search for Python 3.13 release notes (maybe "Python 3.13 release not
Tool called: {'query': 'Python 3.13 release notes', 'max_results': 5}
Tool done: [1] What's New In Python 3.13 — Python 3.14.3 documentation
What's New In Python 3.13 ¶ Editors: Adam Turner and Thomas Wouters This article explains the new features in Python 3.13 , compared to 3.12
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: We need Python 3.13 release notes and today's weather in NYC. We have search results for release notes. Need to fetch the release notes page. Also need weather. Likely use web search for weather NYC t
Tool called: {'max_results': 5, 'query': 'NYC weather today'}
Tool done: [1] Manhattan, New York City, New York - The Weather Channel
Today's and tonight's Manhattan, New York City, New York weather forecast, weather conditions and Doppler radar from The Weather Channel an
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: We need to retrieve Python 3.13 release notes and today's weather in NYC. We have search results. Need to open likely sources for both. For Python, the official docs "What's New In Python 3.13". Let's
Tool called: {'url': 'https://docs.python.org/3/whatsnew/3.13.html', 'max_chars': 2000}
Tool done: index
modules |
next |
previous |
Python »
Greek | Ελληνικά
English
Spanish | español
French | français
Italian | italiano
Japanese | 日本語
Korean | 한국어
Polish | polski
Brazilian Portuguese | Portuguê
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: We have Python 3.13 release notes summary. Need also today's weather in NYC. Let's open a weather site to get current data. Use open_url on a reliable source like weather.com but need specific info. U
Tool called: {'url': 'https://weather.com/weather/today/l/Manhattan+New+York+City+New+York?canonicalCityId=4020d3357937ae0b52673ba25c8906efd1d8011774f10ff04551f34eadf31fdf', 'max_chars': 1500}open_url: Playwright fetch failed for https://weather.com/weather/today/l/Manhattan+New+York+City+New+York?canonicalCityId=4020d3357937ae0b52673ba25c8906efd1d8011774f10ff04551f34eadf31fdf: HTTP 404 from https://weather.com/weather/today/l/Manhattan+New+York+City+New+York?canonicalCityId=4020d3357937ae0b52673ba25c8906efd1d8011774f10ff04551f34eadf31fdf open_url: urllib fetch failed for https://weather.com/weather/today/l/Manhattan+New+York+City+New+York?canonicalCityId=4020d3357937ae0b52673ba25c8906efd1d8011774f10ff04551f34eadf31fdf: HTTP Error 404: Not Found
Tool done: Error: could not fetch https://weather.com/weather/today/l/Manhattan+New+York+City+New+York?canonicalCityId=4020d3357937ae0b52673ba25c8906efd1d8011774f10ff04551f34eadf31fdf — playwright failed: HTTP 4
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: We need today's weather in NYC. Could use another source like weather.gov or AccuWeather or simple API. Let's open a more reliable URL. Use National Weather Service.
Tool called: {'url': 'https://forecast.weather.gov/MapClick.php?textField1=40.71&textField2=-74.01', 'max_chars': 2000}
Tool done: HOME
FORECAST
PAST WEATHER
SAFETY
INFORMATION
EDUCATION
NEWS
SEARCH
ABOUT
View Location Examples
Your local forecast office is
New York, NY
News Headlines
Learn All About Being a COCORAH
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: User asks: "Search for Python 3.13 release notes and today's weather in NYC". Need to provide both pieces of info. We have fetched Python release notes page with summary. Could extract key highlights.
Final: **Python 3.13 – Release Notes (high‑level highlights)**
Source: *What’s New in Python 3.13* (Python documentation)
- **Release date:** 7 Oct 2024.
- **Major language changes**
* New interactive interpreter (a refreshed REPL) with improved UI.
* Experimental **free‑threaded mode** (PEP 703) – allows running Python code without the GIL for certain workloads.
* **Just‑In‑Time (JIT) compiler** (PEP 744) – optional performance boost for hot code paths.
* `locals()` now has defined semafrom shipit_agent import Agent, FileTraceStore
agent = Agent(
llm=llm,
max_iterations=10,
trace_store=FileTraceStore(root_dir=".shipit_traces"),
trace_id="run-2026-04-09-alice",
)from IPython.display import Markdown, display
def markdown(text):
display(Markdown(text))for event in agent.stream(
"Search for Python 3.13 release notes and today's weather in NYC"
):
if event.type == "tool_called":
print("Tool called:")
markdown(f"**Tool Called:** `{event.payload.get('arguments', {})}`")
elif event.type == "tool_completed":
print("Tool done:")
markdown(
f"**Tool Output:**\n```\n{event.payload.get('output', '')[:1000]}\n```"
)
elif event.type == "reasoning_completed":
print("Reasoning: ")
markdown(event.payload.get("content", ""))
elif event.type == "run_completed":
markdown(event.payload.get("content", ""))
else:
markdown(f"**[{event.type}]** {event.message}")[run_started] Agent run started
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning:
The user asks: "Search for Python 3.13 release notes and today's weather in NYC". So need to provide two pieces: Python 3.13 release notes, and today's weather in NYC. Should gather up-to-date info, so use web_search for both topics. Then open URLs for details. Provide summary.
We need to do web searches. Let's search for "Python 3.13 release notes".
Tool called:
Tool Called: {'query': 'Python 3.13 release notes', 'max_results': 5}
Tool done:
Tool Output:
[1] What's New In Python 3.13 — Python 3.14.3 documentation
What's New In Python 3.13 ¶ Editors: Adam Turner and Thomas Wouters This article explains the new features in Python 3.13 , compared to 3.12. Python 3.13 was released on October 7, 2024. For full details, see the changelog.
URL: //duckduckgo.com/l/?uddg=https%3A%2F%2Fdocs.python.org%2F3%2Fwhatsnew%2F3.13.html&rut=1efa42f765ec1a7db1a6eeec0a7b9eab118df2821166b88c237d1441e91fed72
[2] Python 3.13 - Release History, LTS & EOL - VersionLog
Python 3.13 Release Notes Python 3.13.0, released on October 7, 2024, introduces major advancements in performance, concurrency, and developer experience.
URL: //duckduckgo.com/l/?uddg=https%3A%2F%2Fversionlog.com%2Fpython%2F3.13%2F&rut=a344c1429deb5f549336315491ff0bac94071ac066ce29d28af00b6eae1eb4b2
[3] cpython/Doc/whatsnew/3.13.rst at main · python/cpython
Summary -- Release Highlights Python 3.13 is a stable release of the Python programming language, with a mix of changes to the language, th
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning:
We need both Python 3.13 release notes and today's weather in NYC. Need to fetch weather info. We'll search for NYC weather today.
Tool called:
Tool Called: {'max_results': 5, 'query': 'New York City weather today'}
Tool done:
Tool Output:
[1] New York, NY Weather Forecast | AccuWeather
New York , NY Weather Forecast, with current conditions, wind, air quality, and what to expect for the next 3 days.
URL: //duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.accuweather.com%2Fen%2Fus%2Fnew%2Dyork%2F10021%2Fweather%2Dforecast%2F349727&rut=d12472aa45963856a03b496d2712338ee0d0e68923cc9e83f8d1cf2e302140e1
[2] 10-day weather forecast for Manhattan, New York City, New York, United ...
Be prepared with the most accurate 10-day forecast for Manhattan, New York City , New York , United States with highs, lows, chance of precipitation from The Weather Channel and Weather .com
URL: //duckduckgo.com/l/?uddg=https%3A%2F%2Fweather.com%2Fen%2DTO%2Fweather%2Ftenday%2Fl%2FManhattan%2BNew%2BYork%2BCity%2BNew%2BYork%2BUnited%2BStates%3FplaceId%3D4020d3357937ae0b52673ba25c8906efd1d8011774f10ff04551f34eadf31fdf&rut=e9b5a9661ca09a5e9522694395ef367875be8734ffaaa5b4b52a6a0abf39e7d2
[3] 7-Day Forecast 40.71N 73.98W - National Weather Service
Hazardous We
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning:
We need to provide Python 3.13 release notes and today's weather in NYC.
We have search results. Need to open relevant pages to extract info.
Open Python 3.13 what's new page.
Tool called:
Tool Called: {'url': 'https://docs.python.org/3/whatsnew/3.13.html'}
Tool done:
Tool Output:
index
modules |
next |
previous |
Python »
Greek | Ελληνικά
English
Spanish | español
French | français
Italian | italiano
Japanese | 日本語
Korean | 한국어
Polish | polski
Brazilian Portuguese | Português brasileiro
Romanian | Românește
Turkish | Türkçe
Simplified Chinese | 简体中文
Traditional Chinese | 繁體中文
dev (3.15)
3.14.4
3.13
3.12
3.11
3.10
3.9
3.8
3.7
3.6
3.5
3.4
3.3
3.2
3.1
3.0
2.7
2.6
3.14.4 Documentation » What’s New in Python » What’s New In Python 3.13
|
… 22 more lines
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning:
We need to provide both Python 3.13 release notes summary and today's weather in NYC. We have release notes page fetched. Need to extract key points (maybe summary). Also need current weather; we have search results but not content. Need to fetch actual weather page (maybe from weather.com) but that may be dynamic; we could use a simple API like wttr.in which returns text. Let's try open_url to https://wttr.in/New+York?format=3 which gives concise weather.
Tool called:
Tool Called: {'url': 'https://wttr.in/New+York?format=3'}
open_url: Playwright fetch failed for https://wttr.in/New+York?format=3: Page.goto: net::ERR_ABORTED at https://wttr.in/New+York?format=3 Call log: - navigating to "https://wttr.in/New+York?format=3", waiting until "domcontentloaded"
Tool done:
Tool Output:
new york: ☀️ +12°C
[step_started] LLM completion started
Python 3.13 – Release notes (summary)
locals() now has defined semantics when the returned mapping is mutated.PythonFinalizationError, deprecations in argparse, base64.z85encode/decode, copy.replace, default dbm.sqlite3 backend, new os timer‑fd helpers, CLI for random, etc.ssl.create_default_context() now enforces VERIFY_X509_PARTIAL_CHAIN.(Full details are in the official “What’s New in Python 3.13” page: https://docs.python.org/3/whatsnew/3.13.html)
Today's weather in New York City (as of the time of the query)
Source: https://wttr.in/New+York?format=3
Let me know if you need more detail on any of these topics!
for event in agent.stream(
"Search for Python 3.14.4 release notes and today's weather in Warsaw"
):
if event.type == "tool_called":
print("Tool called:")
markdown(f"**Tool Called:** `{event.payload.get('arguments', {})}`")
elif event.type == "tool_completed":
print("Tool done:")
markdown(
f"**Tool Output:**\n```\n{event.payload.get('output', '')[:1000]}\n```"
)
elif event.type == "reasoning_completed":
print("Reasoning: ")
markdown(event.payload.get("content", ""))
elif event.type == "run_completed":
markdown(event.payload.get("content", ""))
else:
markdown(f"**[{event.type}]** {event.message}")[run_started] Agent run started
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning:
We need to provide both: Python 3.14.4 release notes, and today's weather in Warsaw. Need fresh data for weather (today's date). Use web_search then open_url for Python release notes, and web_search/open_url for weather. Possibly use a weather site. Let's search.
Tool called:
Tool Called: {'query': 'Python 3.14.4 release notes', 'max_results': 5}
Tool done:
Tool Output:
[1] Python Release Python 3.14.4 | Python.org
Python 3.14.4 is the fourth maintenance release of 3.14, containing around 337 bugfixes, build improvements and documentation changes since 3.14.3. Major new features of the 3.14 series, compared to 3.13
URL: //duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.python.org%2Fdownloads%2Frelease%2Fpython%2D3144%2F&rut=4b57433242b8a3a3eaf4cad8dec0ed94bd8ef4d04cf800e1b21d98a53c14c9bb
[2] Changelog — Python 3.14.3 documentation
This avoids issues with upgrading Python while it is running. ( Note that such 'in-place' upgrades are not tested.) The tracker remains compatible with subprocesses that use new protocol (that is, subprocesses using Python 3.13.10, 3.14.1 and 3.15). gh-142214: Fix two regressions in dataclasses in Python 3.14.1 related to annotations.
URL: //duckduckgo.com/l/?uddg=https%3A%2F%2Fdocs.python.org%2F3%2Fwhatsnew%2Fchangelog.html&rut=5053dd15419ac522349e2e7b5efefbd7c2a7ce91a4c44a9a6458aa9a91282d64
[3] Python 3.15.0a8, 3.14.4 and 3.13.
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning:
The user asks: "Search for Python 3.14.4 release notes and today's weather in Warsaw". Need to provide both pieces of information.
We have search results for Python 3.14.4 release notes. Let's open the first result.
Tool called:
Tool Called: {'url': 'https://www.python.org/downloads/release/python-3144/'}
Tool done:
Tool Output:
Skip to content
Python
PSF
Docs
PyPI
Jobs
Community
Donate
Search This Site
GO
Socialize
About
Downloads
Documentation
Community
Success Stories
News
Events
Python 3.14.4
Release date: April 7, 2026
This is fourth maintenance release of Python 3.14
Python 3.14.4 is the fourth maintenance release of 3.14, containing around 337 bugfixes, build improvements and documentation changes since 3.14.3.
Major new features of the 3.14 series, compared to 3.13
Some of the major new features and changes in Python 3.14 are:
New features
… 7 more lines
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning:
The user wants both Python 3.14.4 release notes and today's weather in Warsaw. We have fetched release notes page; need to summarize key release notes. Also need today's weather in Warsaw. Need to fetch weather info from a source (e.g., weather.com, openweather). Use web_search to find "Warsaw weather today".
Tool called:
Tool Called: {'max_results': 5, 'query': 'Warsaw weather today'}
Tool done:
Tool Output:
[1] Today's Weather in Warszawa - Hourly Forecast and Conditions
Get the latest hourly weather updates for Warszawa today . Detailed forecast including temperature, wind, rain, snow, and UV index. Stay informed about today's weather conditions in Warszawa.
URL: //duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.easeweather.com%2Feurope%2Fpoland%2Fmazovia%2Fwarszawa%2Ftoday&rut=3dedf7325907f92328e940c240a1553e2d7dd1d46f2891d49f75ef4cf9f46ae9
[2] Warsaw Weather Forecast
12 day Warsaw Weather Forecast. Live Weather Warnings, hourly weather updates. Accurate Warsaw weather today , forecast for sun, rain, wind and temperature.
URL: //duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.weather%2Dforecast.com%2Flocations%2FWarsaw%2Fforecasts%2Flatest&rut=f512cd7bae35b6d3a813f459fa24d6236565d45c9fdf79fb87b30da892ae2d30
[3] Warsaw, Masovia, Poland Hourly Weather | AccuWeather
Hourly weather forecast in Warsaw , Masovia, Poland. Check current conditions in Warsaw , Masovia, Poland with radar, hourly, and more.
U
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning:
We need to provide Python 3.14.4 release notes and today's weather in Warsaw. Already have release notes page from python.org. Need to summarize key points. For weather, need current data. Likely need to open one of the weather pages to get actual data. Let's open a reliable source like weather.com or accuweather. Use open_url on one result.
Tool called:
Tool Called: {'url': 'https://weather.com/weather/today/l/Warsaw+Poland?canonicalCityId=7ed0ae4e25e1adb77367c6f70331d838'}
Tool done:
Tool Output:
Home
Today
Hourly
10 Day
Monthly
Radar
Video
Explore
Severe Weather
Hurricane Central
Tornado Central
Safety & Prep
Health & Wellness
Allergy Tracker
Air Quality Index
Cold & Flu Tracker
Skin
Lifestyle
Home & Garden
Pets & Animals
Recipes
Space & Skywatching
Travel & Outdoors
Product Reviews & Deals
Shop
Home
Today
Hourly
10 Day
Monthly
Radar
Video
Explore
Severe Weather
Hurricane Central
Tornado Central
Safety & Prep
Health & Wellness
… 18 more lines
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning:
We need to provide the Python 3.14.4 release notes and today's weather in Warsaw. We have Python release notes page content; we need to summarize. For weather, the page we opened is weather.com but shows generic data; need current date. The data shows as of 9:00 pm CEST, temperature 48°F, fair. Might be enough. Provide summary.
We should ensure today's date (April 12, 2026). Provide weather details: temperature, conditions, wind, humidity, forecast.
Let's extract relevant info from weather page: In the snippet we see "As of 9:00 pm CEST 48° Fair". Also hourly shows now 46°, clear, etc. Provide summary.
Now craft answer.
Python 3.14.4 Release notes (released April 7 2026)
Overview
Python 3.14.4 is the fourth maintenance release of the 3.14 series. It bundles ≈ 337 bug‑fixes, assorted build improvements and documentation updates over 3.14.3.
Key highlights
| Area | What’s new / changed |
|---|---|
| Free‑threaded interpreter | PEP 779 – free‑threaded Python is now officially supported. |
| Deferred annotation evaluation | PEP 649 – annotations are evaluated lazily, fixing long‑standing semantics issues. |
| Template string literals | PEP 750 – “t‑strings” give you a custom‑string‑processing syntax that mirrors f‑strings. |
| Multiple interpreters | PEP 734 – the stdlib now ships a multiple‑interpreter module. |
| Zstandard compression | PEP 784 – new compression.zstd module for Zstandard algorithm support. |
| Exception syntax | PEP 758 – except/except* can omit the surrounding brackets. |
| Debugger interface | PEP 768 – a zero‑overhead external debugger interface for CPython. |
| UUID extensions | UUID v6‑v8 added; generation of v3‑v5 now up to 40 % faster. |
| Return/break/continue in finally | PEP 765 disallows these statements from exiting a finally block. |
| C‑API improvements | PEP 741 – revamped C‑API for configuring Python. |
| New interpreter type | An optional, high‑performance interpreter for newer compilers (opt‑in). |
| Error‑message upgrades | More informative tracebacks and diagnostics. |
| Built‑in HMAC | Formal‑verification via the HACL* project. |
| Async process inspector | New CLI to inspect running Python processes using asynchronous tasks. |
| Remote pdb | pdb can now attach remotely to a live process. |
| Build changes | • No longer provides PGP signatures – Sigstore is recommended (PEP 761). • macOS/Windows binaries now include an experimental JIT. • Official Android binary releases are now available. |
| Installer shift | The traditional Windows installer is being replaced by a new Python Install Manager (available via Windows Store or direct download). |
For a full, line‑by‑line changelog see the “Full Changelog” section on the release page or the “What’s new in Python 3.14” docs.
Warsaw (Poland) weather – 12 April 2026
| Parameter | Value (as of the latest observation ≈ 21:00 CEST) |
|---|---|
| Temperature | 48 °F (≈ 9 °C) – Fair conditions |
| Feels like | 45 °F (≈ 7 °C) |
| Current condition | Clear skies |
| Wind | 7 mph (≈ 11 km/h) from ESE |
| Humidity | 45 % |
| … 16 more lines |
from shipit_agent.tools import WebSearchTool, OpenURLTool
agent = Agent(
llm=llm,
tools=[WebSearchTool(), OpenURLTool()],
max_iterations=10,
trace_store=FileTraceStore(root_dir=".shipit_traces"),
trace_id="run-2026-04-09-alice",
)for event in agent.stream("Search for new about shipit agent and what is shipiit ai"):
if event.type == "tool_called":
print("Tool called:")
elif event.type == "tool_completed":
print("Tool done:")
elif event.type == "reasoning_completed":
print("Reasoning: ")
elif event.type == "run_completed":
markdown(event.payload.get("content", ""))
else:
markdown(f"**[{event.type}]** {event.message}")[run_started] Agent run started
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: Tool called: Tool done:
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: Tool called: Tool done:
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: Tool called: Tool done:
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: Tool called: Tool done:
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: Tool called: Tool done:
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: Tool called: Tool done:
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: Tool called: Tool done:
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: Tool called: Tool done:
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning: Tool called: Tool done:
[step_started] LLM completion started
[reasoning_started] Model reasoning started
Reasoning:
ShipIt AI – Quick‑look (what it is)
| Feature | Details |
|---|---|
| Core idea | An “AI‑developer‑workspace” that turns a plain‑English request into a full software‑delivery pipeline: parse → implement → review → fix → test → PR → ship. |
| AI engines | Supports up to four different generators (Claude, OpenAI Codex, Google Gemini, and a custom “ShipIt CLI” that can route to Bedrock, Ollama, Groq, Together, OpenRouter, etc.) and > 100 models. |
| Repo‑aware editing | The agent reads the entire repository, validates paths, and prevents out‑of‑scope edits. |
| Visible delivery loop | Every step (code generation, auto‑review, test run, commit) is shown in a UI/graph so the developer can see what the agent is doing, not just the final output. |
| Multi‑messenger integration | The UI can spin up Slack, Discord, and Telegram bots that listen for commands (e.g., “@shipit run the test suite”) and reply with live status updates. |
| Built‑in security / QA | Runs static analysis (Bandit, Semgrep), secret detection, license compliance, container scans, and an AI‑driven penetration‑testing suite (OWASP 2025 coverage). |
| Extensible workflow | 30+ step‑type templates, drag‑and‑drop visual pipeline builder, 17+ MCP integrations (GitHub, GitLab, Jira, DBs, Playwright, etc.). |
| Public‑facing pages | • Product landing: https://shipiit.com/ • LinkedIn announcement (4 days ago): https://www.linkedin.com/posts/shipiit_shipit-a-powerful-ai-coding-agent-with-activity-7447720216366682112-1Z6I • GitHub “ShipIt‑AI” graph project: https://github.com/ship-it-ops/ShipIt-AI • “ShipIt Clean” code‑analysis spinoff: https://shipitclean.com/ • Devpost hackathon entry (2018): https://devpost.com/software/shipit |
Recent news & activity (the “new about ShipIt agent”)
| Date (≈) | Source | Highlight |
|---|---|---|
| 4 days ago | LinkedIn post by ShipIt (35 followers) | Announces a “powerful AI coding agent with a beautiful modern UI” that works across Slack, Discord and Telegram. Shows a concrete workflow where a user asks the bot to run a test suite and receives a live‑streamed result. Includes a wait‑list link to early‑access the product. |
| 2024‑03 (approx.) | ShipIt product site (shipiit.com) | Updated landing page now shows four AI engines, 100+ models, 30+ visual workflow steps and 17+ integrations. Emphasises “repo‑aware before editing”, “visible delivery graph”, and “operator‑first product”. |
| 2024‑02 | ShipIt‑Clean website launch | Introduces a separate service that runs multiple independent AI agents to audit a codebase (feature completeness, architecture, performance, developer experience, scalability) and output a prioritized Opportunity Report. |
| 2024‑02‑20 (GitHub commit) | GitHub – ship‑it‑ops/ShipIt‑AI | Open‑source project that maps a software ecosystem into a Neo4j knowledge graph. Connectors pull data from GitHub, Kubernetes, etc., exposing a queryable graph for downstream AI agents (Claude, Gemini, etc.). |
| 2023‑12 (Devpost) | Devpost “ShipIt” hackathon project | Earlier incarnation of “ShipIt” that combined a smart contract on Ethereum with a ML model predicting project completion time. Demonstrates the team’s long‑standing interest in AI‑assisted project delivery. |
No major press releases have been published in mainstream tech news outlets yet; the most visible public updates are the LinkedIn announcement and the product‑site refresh that rolled out in early 2024.
store = FileTraceStore(root_dir=".shipit_traces")
trace = store.load("run-2026-04-09-alice")
# Pretty print like LangGraph/LangSmith
for i, event in enumerate(trace.events):
indent = (
" "
if event.type in ("tool_called", "tool_completed", "reasoning_completed")
else ""
)
if event.type == "run_started":
print(f"🟢 Run Started: {event.payload.get('prompt', '')}")
elif event.type == "step_started":
print(f"\n📍 Step {event.payload.get('iteration', '?')}")
elif event.type == "reasoning_completed":
print(f" 💭 Reasoning: {event.payload.get('content', '')[:150]}...")
elif event.type == "tool_called":
print(f" 🔧 → {event.payload.get('arguments', {})}")
elif event.type == "tool_completed":
print(f" ✅ ← {event.payload.get('output', '')[:150]}")
elif event.type == "tool_failed":
print(f" ❌ Failed: {event.payload.get('error', '')}")
elif event.type == "run_completed":
usage = event.payload.get("usage", {})
print(f"\n🏁 Done — tokens: {usage.get('total_tokens', 0)}")
print(f" Output: {event.payload.get('content', '')[:300]}")
else:
print(f" [{event.type}] {event.message}")🟢 Run Started: Search for Python 3.13 release notes and today's weather in NYC
📍 Step 1
[reasoning_started] Model reasoning started
💭 Reasoning: The user asks: "Search for Python 3.13 release notes and today's weather in NYC". So need to provide two pieces: Python 3.13 release notes, and today'...
🔧 → {'query': 'Python 3.13 release notes', 'max_results': 5}
✅ ← [1] What's New In Python 3.13 — Python 3.14.3 documentation
What's New In Python 3.13 ¶ Editors: Adam Turner and Thomas Wouters This article explains
📍 Step 2
[reasoning_started] Model reasoning started
💭 Reasoning: We need both Python 3.13 release notes and today's weather in NYC. Need to fetch weather info. We'll search for NYC weather today....
🔧 → {'max_results': 5, 'query': 'New York City weather today'}
✅ ← [1] New York, NY Weather Forecast | AccuWeather
New York , NY Weather Forecast, with current conditions, wind, air quality, and what to expect for the
📍 Step 3
[reasoning_started] Model reasoning started
💭 Reasoning: We need to provide Python 3.13 release notes and today's weather in NYC.
We have search results. Need to open relevant pages to extract info.
Open P...
🔧 → {'url': 'https://docs.python.org/3/whatsnew/3.13.html'}
✅ ← index
modules |
next |
previous |
Python »
Greek | Ελληνικά
English
Spanish | español
French | français
Italian | italiano
Japanese | 日本語
Korean | 한
📍 Step 4
[reasoning_started] Model reasoning started
💭 Reasoning: We need to provide both Python 3.13 release notes summary and today's weather in NYC. We have release notes page fetched. Need to extract key points (...
… 420 more linesfrom shipit_agent import Agent
# ToolSearchTool is included in Agent.with_builtins automatically
agent = Agent.with_builtins(llm=llm)
result = agent.run(
"Use tool_search to find the right tool for fetching a specific URL, "
"then call that tool on https://example.com"
)markdown(f"**Final Result:**\n```\n{result.output}\n```")Final Result:
Here’s the content fetched from **https://example.com** (truncated to the first 1 000 characters):
Example Domain
This domain is for use in documentation examples without needing permission. Avoid use in operations.
Learn more
# ToolSearchTool is included in Agent.with_builtins automatically
from shipit_agent import Agent
agent = Agent.with_builtins(llm=llm)from pydantic import BaseModel
from shipit_agent import Agent
class MovieReview(BaseModel):
title: str
rating: float
summary: str
earning: int
pros: list[str]
cons: list[str]
casts: list[str]
result = agent.run("Review The Dhurandhar: The Revenge", output_schema=MovieReview)
review = result.parsed # MovieReview instance
review.title # "The Dhurandhar: The Revenge"
review.rating # 9.5
review.earning # 1000000
review.pros # ["Groundbreaking visuals", ...]
review.cons # ["Weak storyline", ...]
review.casts # ["Actor 1", "Actor 2", ...]
type(review) # <class 'MovieReview'>__main__.MovieReview
print(f"Title: {review.title}")
print(f"Rating: {review.rating}")
print(f"Earning: ${review.earning}")
print("Pros:")
for p in review.pros:
print(f"- {p}")
print("Cons:")
for c in review.cons:
print(f"- {c}")
print("Casts:")
for cast in review.casts:
print(f"- {cast}")Title: Dhurandhar: The Revenge Rating: 3.5 Earning: $16822200000 Pros: - Strong lead performance by Ranveer Singh - Impressive supporting cast (Arjun Rampal, Sanjay Dutt, R. Madhavan, Sara Arjun) - High‑production values and expansive action set‑pieces - Well‑received soundtrack and technical craftsmanship - Record‑breaking box‑office performance Cons: - Overly long (nearly 4 hours) leading to pacing issues - Graphic violence and gore that alienated many viewers - Criticized for overt nationalist messaging and propaganda - Mixed critical scores (35 % Tomatometer on Rotten Tomatoes) - Limited appeal outside the core Indian market due to political tone Casts: - Ranveer Singh - Arjun Rampal - Sanjay Dutt - R. Madhavan - Sara Arjun - Rakesh Bedi - Gaurav Gera - Danish Pandor - Manav Gohil
resultreview = result.parsed
if review is None:
print("⚠️ No structured output, generating fallback...")
review = MovieReview(
title="The Dhurandhar: The Revenge",
rating=6.5,
summary="A fictional action drama centered on revenge with intense sequences.",
earning=50000000,
pros=["Action scenes", "Lead performance"],
cons=["Predictable story", "Weak pacing"],
casts=["Actor A", "Actor B"],
)⚠️ No structured output, generating fallback...
review = result.parsedreviewfrom pydantic import BaseModel
from shipit_agent import Agent
class MovieReview(BaseModel):
title: str
rating: float
summary: str
pros: list[str]
cons: list[str]
agent = Agent.with_builtins(llm=llm)
result = agent.run("Review The Matrix", output_schema=MovieReview)
review = result.parsed # MovieReview instance
review.title # "The Matrix"
review.rating # 9.5
review.pros # ["Groundbreaking visuals", ...]
type(review) # <class 'MovieReview'>__main__.MovieReview