This is an automated email from the ASF dual-hosted git repository.

ebenizzy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/burr.git


The following commit(s) were added to refs/heads/main by this push:
     new a2d10a6f Burr 0.42.0 release prep (#651)
a2d10a6f is described below

commit a2d10a6fc5ab8343066f67dcf38363b0ae068ad2
Author: Elijah ben Izzy <[email protected]>
AuthorDate: Sun Feb 15 11:41:02 2026 -0800

    Burr 0.42.0 release prep (#651)
    
    * Replace non-standard license headers in 6 notebooks
    
    Replace "Copyright YEAR Apache Software Foundation" format with the
    Apache-recommended "Licensed to the Apache Software Foundation" format.
    The copyright year format is not standard for ASF projects.
    
    * Add Apache license headers to 33 notebooks
    
    Add standard Apache license headers as first code cell to all notebooks
    that were missing them. Apache releases require proper license headers
    in all distributed files for IP compliance.
    
    * Add twine verification to wheel build process
    
    Add twine check to validate wheel metadata before signing and release.
    This catches packaging issues like malformed metadata, missing long
    descriptions, or invalid entry points early in the release process.
    
    * Document twine requirement in release process
    
    Add twine to prerequisites and update build documentation to reflect
    the new metadata validation step. Release managers need to know about
    this dependency before attempting a release.
    
    * Add twine-check command for voter verification
    
    Add twine-check subcommand to allow voters to independently verify wheel
    metadata during release voting. This gives voters an additional tool to
    validate package quality beyond signature and license checks.
    
    * Truncate pyproject.toml description to single line
    
    * Improve twine validation error messages
    
    Show actual twine output when wheel metadata validation fails. This
    helps release managers quickly diagnose and fix packaging issues
    without needing to manually re-run twine.
    
    * Bump version to 0.42.0
    
    * Replace copyright headers in config files with Apache standard
    
    Replace "Copyright YEAR" format with the Apache-recommended
    "Licensed to the Apache Software Foundation" format in all
    configuration and requirements files. The copyright year format
    is not standard for ASF projects.
    
    * Add -src suffix to source release archive name
    
    Rename git archive from apache-burr-{version}-incubating.tar.gz to
    apache-burr-{version}-incubating-src.tar.gz to clearly distinguish
    the source archive from other artifacts in the release.
    
    * removes pyproject.toml update for merge
    
    * fixes pandas 3 compatibility test
    
    * Pre-commit on everything
    
    ---------
    
    Co-authored-by: Elijah ben Izzy <[email protected]>
---
 .pre-commit-config.yaml                            | 25 ++++++-----
 .style.yapf                                        | 25 ++++++-----
 .../s3/deployment/terraform/.terraform.lock.hcl    | 25 ++++++-----
 docs/examples/chatbots/basic-chatbot.ipynb         |  8 ++++
 docs/examples/chatbots/gpt-like-chatbot.ipynb      | 34 +++++++++------
 docs/examples/chatbots/rag-chatbot-hamilton.ipynb  |  8 ++++
 .../simple/choose-your-own-adventure.ipynb         | 39 ++++++++++--------
 docs/examples/simple/counter.ipynb                 |  8 ++++
 docs/examples/simple/cowsay.ipynb                  |  8 ++++
 examples/adaptive-crag/notebook.ipynb              |  7 ++++
 .../graph_db_example/ingest_notebook.ipynb         |  8 ++++
 .../graph_db_example/notebook.ipynb                |  8 ++++
 .../simple_example/notebook.ipynb                  |  8 ++++
 examples/custom-serde/notebook.ipynb               |  8 ++++
 examples/deep-researcher/notebook.ipynb            | 28 ++++---------
 examples/deep-researcher/requirements.txt          | 25 ++++++-----
 examples/deployment/vercel/README.md               |  2 +-
 examples/deployment/vercel/api/counter.py          | 27 ++++++------
 examples/deployment/vercel/app/counter_app.py      |  1 -
 examples/email-assistant/notebook.ipynb            | 16 +-------
 examples/email-assistant/requirements.txt          | 25 ++++++-----
 examples/hamilton-integration/notebook.ipynb       |  7 ++++
 examples/haystack-integration/notebook.ipynb       |  7 ++++
 examples/hello-world-counter/notebook.ipynb        | 16 +-------
 examples/image-telephone/notebook.ipynb            |  8 ++++
 examples/instructor-gemini-flash/notebook.ipynb    |  7 ++++
 examples/llm-adventure-game/notebook.ipynb         |  8 ++++
 .../hamilton/notebook.ipynb                        |  8 ++++
 .../multi-agent-collaboration/lcel/notebook.ipynb  |  8 ++++
 examples/multi-modal-chatbot/burr_demo.ipynb       | 46 ++++++++-------------
 examples/multi-modal-chatbot/notebook.ipynb        | 16 +-------
 examples/multi-modal-chatbot/requirements.txt      | 25 ++++++-----
 examples/opentelemetry/notebook.ipynb              |  8 ++++
 examples/other-examples/cowsay/notebook.ipynb      |  8 ++++
 examples/parallelism/notebook.ipynb                |  8 ++++
 examples/rag-lancedb-ingestion/notebook.ipynb      |  7 ++++
 examples/ray/notebook.ipynb                        |  8 ++++
 examples/recursive/notebook.ipynb                  |  8 ++++
 examples/simple-chatbot-intro/notebook.ipynb       |  8 ++++
 examples/streaming-fastapi/notebook.ipynb          | 16 +-------
 examples/streaming-overview/notebook.ipynb         |  8 ++++
 examples/talks/data_for_ai_oct_2024.ipynb          |  8 ++++
 examples/test-case-creation/notebook.ipynb         |  8 ++++
 examples/tool-calling/notebook.ipynb               |  8 ++++
 examples/tracing-and-spans/burr_otel_demo.ipynb    |  8 ++++
 examples/tracing-and-spans/notebook.ipynb          |  8 ++++
 examples/typed-state/notebook.ipynb                |  8 ++++
 .../youtube-to-social-media-post/notebook.ipynb    |  7 ++++
 pyproject.toml                                     | 19 +--------
 scripts/README.md                                  | 13 +++---
 scripts/apache_release.py                          | 48 ++++++++++++++++++----
 scripts/verify_apache_artifacts.py                 | 42 ++++++++++++++++++-
 setup.cfg                                          | 25 ++++++-----
 telemetry/ui/.eslintignore                         | 25 ++++++-----
 telemetry/ui/.prettierignore                       | 25 ++++++-----
 telemetry/ui/public/robots.txt                     | 25 ++++++-----
 tests/integrations/serde/test_pandas.py            | 16 ++++++--
 57 files changed, 569 insertions(+), 302 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index aee19ae4..9450bab7 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,16 +1,19 @@
-# Copyright 2026 Apache Software Foundation
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+#   http://www.apache.org/licenses/LICENSE-2.0
 #
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
 
 # pre-commit hooks require a user to have installed `pre-commit`:
 #   $ brew install pre-commit
diff --git a/.style.yapf b/.style.yapf
index 8a3aba20..0bceb67e 100644
--- a/.style.yapf
+++ b/.style.yapf
@@ -1,16 +1,19 @@
-# Copyright 2026 Apache Software Foundation
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+#   http://www.apache.org/licenses/LICENSE-2.0
 #
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
 
 [style]
 based_on_style = google
diff --git a/burr/tracking/server/s3/deployment/terraform/.terraform.lock.hcl 
b/burr/tracking/server/s3/deployment/terraform/.terraform.lock.hcl
index 4fbf52a1..409759d4 100644
--- a/burr/tracking/server/s3/deployment/terraform/.terraform.lock.hcl
+++ b/burr/tracking/server/s3/deployment/terraform/.terraform.lock.hcl
@@ -1,16 +1,19 @@
-# Copyright 2026 Apache Software Foundation
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+#   http://www.apache.org/licenses/LICENSE-2.0
 #
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
 
 # This file is maintained automatically by "terraform init".
 # Manual edits may be lost in future updates.
diff --git a/docs/examples/chatbots/basic-chatbot.ipynb 
b/docs/examples/chatbots/basic-chatbot.ipynb
index db959573..1688a5af 100644
--- a/docs/examples/chatbots/basic-chatbot.ipynb
+++ b/docs/examples/chatbots/basic-chatbot.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "72xar2zywy",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "61278d3e-958b-49ee-94b8-2ee1f5e58773",
diff --git a/docs/examples/chatbots/gpt-like-chatbot.ipynb 
b/docs/examples/chatbots/gpt-like-chatbot.ipynb
index dd875bc6..7a4351b1 100644
--- a/docs/examples/chatbots/gpt-like-chatbot.ipynb
+++ b/docs/examples/chatbots/gpt-like-chatbot.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "y14cel7pcg",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "f63df3e4b8d4fdba",
@@ -680,19 +688,19 @@
      "evalue": "Demo error",
      "output_type": "error",
      "traceback": [
-      
"\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
-      "\u001B[0;31mValueError\u001B[0m                                
Traceback (most recent call last)",
-      "Cell \u001B[0;32mIn[12], line 5\u001B[0m\n\u001B[1;32m      3\u001B[0m 
\u001B[38;5;28;01mif\u001B[39;00m 
\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mquit\u001B[39m\u001B[38;5;124m\"\u001B[39m
 \u001B[38;5;241m==\u001B[39m 
user_input\u001B[38;5;241m.\u001B[39mlower():\n\u001B[1;32m      4\u001B[0m     
\u001B[38;5;28;01mbreak\u001B[39;00m\n\u001B[0;32m----> 5\u001B[0m last_action, 
action_result, app_state \u001B[38;5;241m=\u001B[39m 
\u001B[43mapp\u001B[49m\u001B[38;5;241;43m.\u001B[3 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/telemetry.py:273\u001B[0m, in 
\u001B[0;36mcapture_function_usage.<locals>.wrapped_fn\u001B[0;34m(*args, 
**kwargs)\u001B[0m\n\u001B[1;32m    270\u001B[0m 
\u001B[38;5;129m@functools\u001B[39m\u001B[38;5;241m.\u001B[39mwraps(call_fn)\n\u001B[1;32m
    271\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m 
\u001B[38;5;21mwrapped_fn\u001B[39m(\u001B[38;5;241m*\u001B[39margs, 
\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs):\n\u001B[1;32m    
27 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:878\u001B[0m, 
in \u001B[0;36mApplication.run\u001B[0;34m(self, halt_before, halt_after, 
inputs)\u001B[0m\n\u001B[1;32m    876\u001B[0m 
\u001B[38;5;28;01mwhile\u001B[39;00m 
\u001B[38;5;28;01mTrue\u001B[39;00m:\n\u001B[1;32m    877\u001B[0m     
\u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 878\u001B[0m         
\u001B[38;5;28;43mnext\u001B[39;49m\u001B[43m(\u001B[49m\u001B[43mgen\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1
 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:823\u001B[0m, 
in \u001B[0;36mApplication.iterate\u001B[0;34m(self, halt_before, halt_after, 
inputs)\u001B[0m\n\u001B[1;32m    820\u001B[0m prior_action: Optional[Action] 
\u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[1;32m   
 821\u001B[0m \u001B[38;5;28;01mwhile\u001B[39;00m 
\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mhas_next_action():\n\u001B[1;32m
    822\u001B[0m     \u001B[38;5;66;03 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:495\u001B[0m, 
in \u001B[0;36mApplication.step\u001B[0;34m(self, 
inputs)\u001B[0m\n\u001B[1;32m    492\u001B[0m \u001B[38;5;66;03m# we need to 
increment the sequence before we start computing\u001B[39;00m\n\u001B[1;32m    
493\u001B[0m \u001B[38;5;66;03m# that way if we're replaying from state, we 
don't get stuck\u001B[39;00m\n\u001B[1;32m    494\u001B[0m 
\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_increment_sequ [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:548\u001B[0m, 
in \u001B[0;36mApplication._step\u001B[0;34m(self, inputs, 
_run_hooks)\u001B[0m\n\u001B[1;32m    546\u001B[0m     exc 
\u001B[38;5;241m=\u001B[39m e\n\u001B[1;32m    547\u001B[0m     
logger\u001B[38;5;241m.\u001B[39mexception(_format_BASE_ERROR_MESSAGE(next_action,
 \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_state, 
inputs))\n\u001B[0;32m--> 548\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m 
e\n\ [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:534\u001B[0m, 
in \u001B[0;36mApplication._step\u001B[0;34m(self, inputs, 
_run_hooks)\u001B[0m\n\u001B[1;32m    532\u001B[0m 
\u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[1;32m    533\u001B[0m     
\u001B[38;5;28;01mif\u001B[39;00m 
next_action\u001B[38;5;241m.\u001B[39msingle_step:\n\u001B[0;32m--> 
534\u001B[0m         result, new_state \u001B[38;5;241m=\u001B[39m 
\u001B[43m_run_single_step_action\u001B[49m\u001B[43m(\u001B[49m [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:233\u001B[0m, 
in \u001B[0;36m_run_single_step_action\u001B[0;34m(action, state, 
inputs)\u001B[0m\n\u001B[1;32m    230\u001B[0m \u001B[38;5;66;03m# TODO -- 
guard all reads/writes with a subset of the state\u001B[39;00m\n\u001B[1;32m    
231\u001B[0m 
action\u001B[38;5;241m.\u001B[39mvalidate_inputs(inputs)\n\u001B[1;32m    
232\u001B[0m result, new_state \u001B[38;5;241m=\u001B[39m 
_adjust_single_step_output(\n\u001B[0;32m--> 2 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/action.py:533\u001B[0m, in 
\u001B[0;36mFunctionBasedAction.run_and_update\u001B[0;34m(self, state, 
**run_kwargs)\u001B[0m\n\u001B[1;32m    532\u001B[0m 
\u001B[38;5;28;01mdef\u001B[39;00m 
\u001B[38;5;21mrun_and_update\u001B[39m(\u001B[38;5;28mself\u001B[39m, state: 
State, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mrun_kwargs) 
\u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m 
\u001B[38;5;28mtuple\u001B[39m[\u001B[38;5;28mdic [...]
-      "Cell \u001B[0;32mIn[8], line 94\u001B[0m, in 
\u001B[0;36mimage_response\u001B[0;34m(state, model)\u001B[0m\n\u001B[1;32m     
91\u001B[0m 
\u001B[38;5;129m@action\u001B[39m(reads\u001B[38;5;241m=\u001B[39m[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mprompt\u001B[39m\u001B[38;5;124m\"\u001B[39m,
 
\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mchat_history\u001B[39m\u001B[38;5;124m\"\u001B[39m,
 
\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmode\u001B[39m\u001B[38;5;124m\"\u001B[39m],
 writes [...]
-      "\u001B[0;31mValueError\u001B[0m: Demo error"
+      
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mValueError\u001b[0m                                
Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[12], line 5\u001b[0m\n\u001b[1;32m      3\u001b[0m 
\u001b[38;5;28;01mif\u001b[39;00m 
\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mquit\u001b[39m\u001b[38;5;124m\"\u001b[39m
 \u001b[38;5;241m==\u001b[39m 
user_input\u001b[38;5;241m.\u001b[39mlower():\n\u001b[1;32m      4\u001b[0m     
\u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[0;32m----> 5\u001b[0m last_action, 
action_result, app_state \u001b[38;5;241m=\u001b[39m 
\u001b[43mapp\u001b[49m\u001b[38;5;241;43m.\u001b[3 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/telemetry.py:273\u001b[0m, in 
\u001b[0;36mcapture_function_usage.<locals>.wrapped_fn\u001b[0;34m(*args, 
**kwargs)\u001b[0m\n\u001b[1;32m    270\u001b[0m 
\u001b[38;5;129m@functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(call_fn)\n\u001b[1;32m
    271\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m 
\u001b[38;5;21mwrapped_fn\u001b[39m(\u001b[38;5;241m*\u001b[39margs, 
\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m    
27 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:878\u001b[0m, 
in \u001b[0;36mApplication.run\u001b[0;34m(self, halt_before, halt_after, 
inputs)\u001b[0m\n\u001b[1;32m    876\u001b[0m 
\u001b[38;5;28;01mwhile\u001b[39;00m 
\u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m    877\u001b[0m     
\u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 878\u001b[0m         
\u001b[38;5;28;43mnext\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mgen\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1
 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:823\u001b[0m, 
in \u001b[0;36mApplication.iterate\u001b[0;34m(self, halt_before, halt_after, 
inputs)\u001b[0m\n\u001b[1;32m    820\u001b[0m prior_action: Optional[Action] 
\u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m   
 821\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m 
\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhas_next_action():\n\u001b[1;32m
    822\u001b[0m     \u001b[38;5;66;03 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:495\u001b[0m, 
in \u001b[0;36mApplication.step\u001b[0;34m(self, 
inputs)\u001b[0m\n\u001b[1;32m    492\u001b[0m \u001b[38;5;66;03m# we need to 
increment the sequence before we start computing\u001b[39;00m\n\u001b[1;32m    
493\u001b[0m \u001b[38;5;66;03m# that way if we're replaying from state, we 
don't get stuck\u001b[39;00m\n\u001b[1;32m    494\u001b[0m 
\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_increment_sequ [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:548\u001b[0m, 
in \u001b[0;36mApplication._step\u001b[0;34m(self, inputs, 
_run_hooks)\u001b[0m\n\u001b[1;32m    546\u001b[0m     exc 
\u001b[38;5;241m=\u001b[39m e\n\u001b[1;32m    547\u001b[0m     
logger\u001b[38;5;241m.\u001b[39mexception(_format_BASE_ERROR_MESSAGE(next_action,
 \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_state, 
inputs))\n\u001b[0;32m--> 548\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m 
e\n\ [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:534\u001b[0m, 
in \u001b[0;36mApplication._step\u001b[0;34m(self, inputs, 
_run_hooks)\u001b[0m\n\u001b[1;32m    532\u001b[0m 
\u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m    533\u001b[0m     
\u001b[38;5;28;01mif\u001b[39;00m 
next_action\u001b[38;5;241m.\u001b[39msingle_step:\n\u001b[0;32m--> 
534\u001b[0m         result, new_state \u001b[38;5;241m=\u001b[39m 
\u001b[43m_run_single_step_action\u001b[49m\u001b[43m(\u001b[49m [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:233\u001b[0m, 
in \u001b[0;36m_run_single_step_action\u001b[0;34m(action, state, 
inputs)\u001b[0m\n\u001b[1;32m    230\u001b[0m \u001b[38;5;66;03m# TODO -- 
guard all reads/writes with a subset of the state\u001b[39;00m\n\u001b[1;32m    
231\u001b[0m 
action\u001b[38;5;241m.\u001b[39mvalidate_inputs(inputs)\n\u001b[1;32m    
232\u001b[0m result, new_state \u001b[38;5;241m=\u001b[39m 
_adjust_single_step_output(\n\u001b[0;32m--> 2 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/action.py:533\u001b[0m, in 
\u001b[0;36mFunctionBasedAction.run_and_update\u001b[0;34m(self, state, 
**run_kwargs)\u001b[0m\n\u001b[1;32m    532\u001b[0m 
\u001b[38;5;28;01mdef\u001b[39;00m 
\u001b[38;5;21mrun_and_update\u001b[39m(\u001b[38;5;28mself\u001b[39m, state: 
State, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mrun_kwargs) 
\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m 
\u001b[38;5;28mtuple\u001b[39m[\u001b[38;5;28mdic [...]
+      "Cell \u001b[0;32mIn[8], line 94\u001b[0m, in 
\u001b[0;36mimage_response\u001b[0;34m(state, model)\u001b[0m\n\u001b[1;32m     
91\u001b[0m 
\u001b[38;5;129m@action\u001b[39m(reads\u001b[38;5;241m=\u001b[39m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mprompt\u001b[39m\u001b[38;5;124m\"\u001b[39m,
 
\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mchat_history\u001b[39m\u001b[38;5;124m\"\u001b[39m,
 
\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmode\u001b[39m\u001b[38;5;124m\"\u001b[39m],
 writes [...]
+      "\u001b[0;31mValueError\u001b[0m: Demo error"
      ]
     }
    ],
diff --git a/docs/examples/chatbots/rag-chatbot-hamilton.ipynb 
b/docs/examples/chatbots/rag-chatbot-hamilton.ipynb
index d8c54096..a537d1ca 100644
--- a/docs/examples/chatbots/rag-chatbot-hamilton.ipynb
+++ b/docs/examples/chatbots/rag-chatbot-hamilton.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "8gtpynaajbp",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "1622e1563a35aa32",
diff --git a/docs/examples/simple/choose-your-own-adventure.ipynb 
b/docs/examples/simple/choose-your-own-adventure.ipynb
index 78aab4f8..6a3bea61 100644
--- a/docs/examples/simple/choose-your-own-adventure.ipynb
+++ b/docs/examples/simple/choose-your-own-adventure.ipynb
@@ -1,5 +1,12 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "metadata": {},
@@ -262,22 +269,22 @@
      "evalue": "Interrupted by user",
      "output_type": "error",
      "traceback": [
-      
"\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
-      "\u001B[0;31mKeyboardInterrupt\u001B[0m                         
Traceback (most recent call last)",
-      "Cell \u001B[0;32mIn[15], line 1\u001B[0m\n\u001B[0;32m----> 1\u001B[0m 
action, state, result \u001B[38;5;241m=\u001B[39m 
\u001B[43mapp\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mrun\u001B[49m\u001B[43m(\u001B[49m\u001B[43mhalt_after\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43m[\u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mwin\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m]\u001B[49m\u001B[43m)\u001B[49m\n",
-      "File \u001B[0;32m~/dagworks/burr/burr/telemetry.py:276\u001B[0m, in 
\u001B[0;36mcapture_function_usage.<locals>.wrapped_fn\u001B[0;34m(*args, 
**kwargs)\u001B[0m\n\u001B[1;32m    273\u001B[0m 
\u001B[38;5;129m@functools\u001B[39m\u001B[38;5;241m.\u001B[39mwraps(call_fn)\n\u001B[1;32m
    274\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m 
\u001B[38;5;21mwrapped_fn\u001B[39m(\u001B[38;5;241m*\u001B[39margs, 
\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs):\n\u001B[1;32m    
27 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:672\u001B[0m, 
in 
\u001B[0;36m_call_execute_method_pre_post.__call__.<locals>.wrapper_sync\u001B[0;34m(app_self,
 *args, **kwargs)\u001B[0m\n\u001B[1;32m    670\u001B[0m exc 
\u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[1;32m   
 671\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 672\u001B[0m 
    \u001B[38;5;28;01mreturn\u001B[39;00m 
\u001B[43mfn\u001B[49m\u001B[43m(\u001B[49m\u001B[43m [...]
-      "File 
\u001B[0;32m~/dagworks/burr/burr/core/application.py:1243\u001B[0m, in 
\u001B[0;36mApplication.run\u001B[0;34m(self, halt_before, halt_after, 
inputs)\u001B[0m\n\u001B[1;32m   1241\u001B[0m 
\u001B[38;5;28;01mwhile\u001B[39;00m 
\u001B[38;5;28;01mTrue\u001B[39;00m:\n\u001B[1;32m   1242\u001B[0m     
\u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m-> 1243\u001B[0m         
\u001B[38;5;28;43mnext\u001B[39;49m\u001B[43m(\u001B[49m\u001B[43mgen\u001B[49m\u001B[43m)\u001B[49m\n\u001B[
 [...]
-      "File 
\u001B[0;32m~/dagworks/burr/burr/core/application.py:1186\u001B[0m, in 
\u001B[0;36mApplication.iterate\u001B[0;34m(self, halt_before, halt_after, 
inputs)\u001B[0m\n\u001B[1;32m   1183\u001B[0m prior_action: Optional[Action] 
\u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[1;32m   
1184\u001B[0m \u001B[38;5;28;01mwhile\u001B[39;00m 
\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mhas_next_action():\n\u001B[1;32m
   1185\u001B[0m     \u001B[38;5;66;0 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:672\u001B[0m, 
in 
\u001B[0;36m_call_execute_method_pre_post.__call__.<locals>.wrapper_sync\u001B[0;34m(app_self,
 *args, **kwargs)\u001B[0m\n\u001B[1;32m    670\u001B[0m exc 
\u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[1;32m   
 671\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 672\u001B[0m 
    \u001B[38;5;28;01mreturn\u001B[39;00m 
\u001B[43mfn\u001B[49m\u001B[43m(\u001B[49m\u001B[43m [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:843\u001B[0m, 
in \u001B[0;36mApplication.step\u001B[0;34m(self, 
inputs)\u001B[0m\n\u001B[1;32m    840\u001B[0m \u001B[38;5;66;03m# we need to 
increment the sequence before we start computing\u001B[39;00m\n\u001B[1;32m    
841\u001B[0m \u001B[38;5;66;03m# that way if we're replaying from state, we 
don't get stuck\u001B[39;00m\n\u001B[1;32m    842\u001B[0m 
\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_increment_sequ [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:885\u001B[0m, 
in \u001B[0;36mApplication._step\u001B[0;34m(self, inputs, 
_run_hooks)\u001B[0m\n\u001B[1;32m    883\u001B[0m 
\u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[1;32m    884\u001B[0m     
\u001B[38;5;28;01mif\u001B[39;00m 
next_action\u001B[38;5;241m.\u001B[39msingle_step:\n\u001B[0;32m--> 
885\u001B[0m         result, new_state \u001B[38;5;241m=\u001B[39m 
\u001B[43m_run_single_step_action\u001B[49m\u001B[43m(\u001B[49m [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:287\u001B[0m, 
in \u001B[0;36m_run_single_step_action\u001B[0;34m(action, state, 
inputs)\u001B[0m\n\u001B[1;32m    284\u001B[0m \u001B[38;5;66;03m# TODO -- 
guard all reads/writes with a subset of the state\u001B[39;00m\n\u001B[1;32m    
285\u001B[0m 
action\u001B[38;5;241m.\u001B[39mvalidate_inputs(inputs)\n\u001B[1;32m    
286\u001B[0m result, new_state \u001B[38;5;241m=\u001B[39m 
_adjust_single_step_output(\n\u001B[0;32m--> 2 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/action.py:655\u001B[0m, in 
\u001B[0;36mFunctionBasedAction.run_and_update\u001B[0;34m(self, state, 
**run_kwargs)\u001B[0m\n\u001B[1;32m    654\u001B[0m 
\u001B[38;5;28;01mdef\u001B[39;00m 
\u001B[38;5;21mrun_and_update\u001B[39m(\u001B[38;5;28mself\u001B[39m, state: 
State, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mrun_kwargs) 
\u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m 
\u001B[38;5;28mtuple\u001B[39m[\u001B[38;5;28mdic [...]
-      "Cell \u001B[0;32mIn[12], line 12\u001B[0m, in 
\u001B[0;36mprompt_for_challenge\u001B[0;34m(state)\u001B[0m\n\u001B[1;32m     
10\u001B[0m \u001B[38;5;250m\u001B[39m\u001B[38;5;124;03m\"\"\"Request user 
input to solve the current challenge\"\"\"\u001B[39;00m\n\u001B[1;32m     
11\u001B[0m current_challenge \u001B[38;5;241m=\u001B[39m 
state[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mcurrent_challenge\u001B[39m\u001B[38;5;124m\"\u001B[39m]\n\u001B[0;32m--->
 12\u001B[0m user_response \ [...]
-      "File 
\u001B[0;32m~/.pyenv/versions/burr-py310/lib/python3.10/site-packages/ipykernel/kernelbase.py:1270\u001B[0m,
 in \u001B[0;36mKernel.raw_input\u001B[0;34m(self, 
prompt)\u001B[0m\n\u001B[1;32m   1268\u001B[0m     msg 
\u001B[38;5;241m=\u001B[39m 
\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mraw_input was called, but this 
frontend does not support input 
requests.\u001B[39m\u001B[38;5;124m\"\u001B[39m\n\u001B[1;32m   1269\u001B[0m   
  \u001B[38;5;28;01mraise\u001B[39;00m StdinNotImpl [...]
-      "File 
\u001B[0;32m~/.pyenv/versions/burr-py310/lib/python3.10/site-packages/ipykernel/kernelbase.py:1313\u001B[0m,
 in \u001B[0;36mKernel._input_request\u001B[0;34m(self, prompt, ident, parent, 
password)\u001B[0m\n\u001B[1;32m   1310\u001B[0m 
\u001B[38;5;28;01mexcept\u001B[39;00m 
\u001B[38;5;167;01mKeyboardInterrupt\u001B[39;00m:\n\u001B[1;32m   
1311\u001B[0m     \u001B[38;5;66;03m# re-raise KeyboardInterrupt, to truncate 
traceback\u001B[39;00m\n\u001B[1;32m   1312\u001B[0m     msg  [...]
-      "\u001B[0;31mKeyboardInterrupt\u001B[0m: Interrupted by user"
+      
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         
Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[15], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m 
action, state, result \u001b[38;5;241m=\u001b[39m 
\u001b[43mapp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43mhalt_after\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mwin\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n",
+      "File \u001b[0;32m~/dagworks/burr/burr/telemetry.py:276\u001b[0m, in 
\u001b[0;36mcapture_function_usage.<locals>.wrapped_fn\u001b[0;34m(*args, 
**kwargs)\u001b[0m\n\u001b[1;32m    273\u001b[0m 
\u001b[38;5;129m@functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(call_fn)\n\u001b[1;32m
    274\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m 
\u001b[38;5;21mwrapped_fn\u001b[39m(\u001b[38;5;241m*\u001b[39margs, 
\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m    
27 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:672\u001b[0m, 
in 
\u001b[0;36m_call_execute_method_pre_post.__call__.<locals>.wrapper_sync\u001b[0;34m(app_self,
 *args, **kwargs)\u001b[0m\n\u001b[1;32m    670\u001b[0m exc 
\u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m   
 671\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 672\u001b[0m 
    \u001b[38;5;28;01mreturn\u001b[39;00m 
\u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[43m [...]
+      "File 
\u001b[0;32m~/dagworks/burr/burr/core/application.py:1243\u001b[0m, in 
\u001b[0;36mApplication.run\u001b[0;34m(self, halt_before, halt_after, 
inputs)\u001b[0m\n\u001b[1;32m   1241\u001b[0m 
\u001b[38;5;28;01mwhile\u001b[39;00m 
\u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m   1242\u001b[0m     
\u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1243\u001b[0m         
\u001b[38;5;28;43mnext\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mgen\u001b[49m\u001b[43m)\u001b[49m\n\u001b[
 [...]
+      "File 
\u001b[0;32m~/dagworks/burr/burr/core/application.py:1186\u001b[0m, in 
\u001b[0;36mApplication.iterate\u001b[0;34m(self, halt_before, halt_after, 
inputs)\u001b[0m\n\u001b[1;32m   1183\u001b[0m prior_action: Optional[Action] 
\u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m   
1184\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m 
\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhas_next_action():\n\u001b[1;32m
   1185\u001b[0m     \u001b[38;5;66;0 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:672\u001b[0m, 
in 
\u001b[0;36m_call_execute_method_pre_post.__call__.<locals>.wrapper_sync\u001b[0;34m(app_self,
 *args, **kwargs)\u001b[0m\n\u001b[1;32m    670\u001b[0m exc 
\u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m   
 671\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 672\u001b[0m 
    \u001b[38;5;28;01mreturn\u001b[39;00m 
\u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[43m [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:843\u001b[0m, 
in \u001b[0;36mApplication.step\u001b[0;34m(self, 
inputs)\u001b[0m\n\u001b[1;32m    840\u001b[0m \u001b[38;5;66;03m# we need to 
increment the sequence before we start computing\u001b[39;00m\n\u001b[1;32m    
841\u001b[0m \u001b[38;5;66;03m# that way if we're replaying from state, we 
don't get stuck\u001b[39;00m\n\u001b[1;32m    842\u001b[0m 
\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_increment_sequ [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:885\u001b[0m, 
in \u001b[0;36mApplication._step\u001b[0;34m(self, inputs, 
_run_hooks)\u001b[0m\n\u001b[1;32m    883\u001b[0m 
\u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m    884\u001b[0m     
\u001b[38;5;28;01mif\u001b[39;00m 
next_action\u001b[38;5;241m.\u001b[39msingle_step:\n\u001b[0;32m--> 
885\u001b[0m         result, new_state \u001b[38;5;241m=\u001b[39m 
\u001b[43m_run_single_step_action\u001b[49m\u001b[43m(\u001b[49m [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:287\u001b[0m, 
in \u001b[0;36m_run_single_step_action\u001b[0;34m(action, state, 
inputs)\u001b[0m\n\u001b[1;32m    284\u001b[0m \u001b[38;5;66;03m# TODO -- 
guard all reads/writes with a subset of the state\u001b[39;00m\n\u001b[1;32m    
285\u001b[0m 
action\u001b[38;5;241m.\u001b[39mvalidate_inputs(inputs)\n\u001b[1;32m    
286\u001b[0m result, new_state \u001b[38;5;241m=\u001b[39m 
_adjust_single_step_output(\n\u001b[0;32m--> 2 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/action.py:655\u001b[0m, in 
\u001b[0;36mFunctionBasedAction.run_and_update\u001b[0;34m(self, state, 
**run_kwargs)\u001b[0m\n\u001b[1;32m    654\u001b[0m 
\u001b[38;5;28;01mdef\u001b[39;00m 
\u001b[38;5;21mrun_and_update\u001b[39m(\u001b[38;5;28mself\u001b[39m, state: 
State, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mrun_kwargs) 
\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m 
\u001b[38;5;28mtuple\u001b[39m[\u001b[38;5;28mdic [...]
+      "Cell \u001b[0;32mIn[12], line 12\u001b[0m, in 
\u001b[0;36mprompt_for_challenge\u001b[0;34m(state)\u001b[0m\n\u001b[1;32m     
10\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Request user 
input to solve the current challenge\"\"\"\u001b[39;00m\n\u001b[1;32m     
11\u001b[0m current_challenge \u001b[38;5;241m=\u001b[39m 
state[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcurrent_challenge\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[0;32m--->
 12\u001b[0m user_response \ [...]
+      "File 
\u001b[0;32m~/.pyenv/versions/burr-py310/lib/python3.10/site-packages/ipykernel/kernelbase.py:1270\u001b[0m,
 in \u001b[0;36mKernel.raw_input\u001b[0;34m(self, 
prompt)\u001b[0m\n\u001b[1;32m   1268\u001b[0m     msg 
\u001b[38;5;241m=\u001b[39m 
\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mraw_input was called, but this 
frontend does not support input 
requests.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m   1269\u001b[0m   
  \u001b[38;5;28;01mraise\u001b[39;00m StdinNotImpl [...]
+      "File 
\u001b[0;32m~/.pyenv/versions/burr-py310/lib/python3.10/site-packages/ipykernel/kernelbase.py:1313\u001b[0m,
 in \u001b[0;36mKernel._input_request\u001b[0;34m(self, prompt, ident, parent, 
password)\u001b[0m\n\u001b[1;32m   1310\u001b[0m 
\u001b[38;5;28;01mexcept\u001b[39;00m 
\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m:\n\u001b[1;32m   
1311\u001b[0m     \u001b[38;5;66;03m# re-raise KeyboardInterrupt, to truncate 
traceback\u001b[39;00m\n\u001b[1;32m   1312\u001b[0m     msg  [...]
+      "\u001b[0;31mKeyboardInterrupt\u001b[0m: Interrupted by user"
      ]
     }
    ],
diff --git a/docs/examples/simple/counter.ipynb 
b/docs/examples/simple/counter.ipynb
index 838940dc..1b961c3e 100644
--- a/docs/examples/simple/counter.ipynb
+++ b/docs/examples/simple/counter.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "jgwmgsmi5z",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "49dab42f",
diff --git a/docs/examples/simple/cowsay.ipynb 
b/docs/examples/simple/cowsay.ipynb
index a65cb543..c54886eb 100644
--- a/docs/examples/simple/cowsay.ipynb
+++ b/docs/examples/simple/cowsay.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "fjksj6jy45q",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "23493882",
diff --git a/examples/adaptive-crag/notebook.ipynb 
b/examples/adaptive-crag/notebook.ipynb
index 626744c4..4306c27a 100644
--- a/examples/adaptive-crag/notebook.ipynb
+++ b/examples/adaptive-crag/notebook.ipynb
@@ -1,5 +1,12 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "metadata": {},
diff --git a/examples/conversational-rag/graph_db_example/ingest_notebook.ipynb 
b/examples/conversational-rag/graph_db_example/ingest_notebook.ipynb
index a56efcdd..d18436b9 100644
--- a/examples/conversational-rag/graph_db_example/ingest_notebook.ipynb
+++ b/examples/conversational-rag/graph_db_example/ingest_notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "z27s4nl744c",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "code",
    "execution_count": null,
diff --git a/examples/conversational-rag/graph_db_example/notebook.ipynb 
b/examples/conversational-rag/graph_db_example/notebook.ipynb
index 45d8ba71..13758a35 100644
--- a/examples/conversational-rag/graph_db_example/notebook.ipynb
+++ b/examples/conversational-rag/graph_db_example/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "d5w7n7aa8lk",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "code",
    "execution_count": null,
diff --git a/examples/conversational-rag/simple_example/notebook.ipynb 
b/examples/conversational-rag/simple_example/notebook.ipynb
index c1256ffa..fa0d4d66 100644
--- a/examples/conversational-rag/simple_example/notebook.ipynb
+++ b/examples/conversational-rag/simple_example/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "oq9sb8jkotm",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "1622e1563a35aa32",
diff --git a/examples/custom-serde/notebook.ipynb 
b/examples/custom-serde/notebook.ipynb
index fbe4a9b3..825a044a 100644
--- a/examples/custom-serde/notebook.ipynb
+++ b/examples/custom-serde/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "apns7ccbyf",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "code",
    "execution_count": null,
diff --git a/examples/deep-researcher/notebook.ipynb 
b/examples/deep-researcher/notebook.ipynb
index 6673870b..6243b2eb 100644
--- a/examples/deep-researcher/notebook.ipynb
+++ b/examples/deep-researcher/notebook.ipynb
@@ -5,21 +5,7 @@
    "cell_type": "code",
    "outputs": [],
    "execution_count": null,
-   "source": [
-    "# Copyright 2026 Apache Software Foundation\n",
-    "#\n",
-    "# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
-    "# you may not use this file except in compliance with the License.\n",
-    "# You may obtain a copy of the License at\n",
-    "#\n",
-    "#     http://www.apache.org/licenses/LICENSE-2.0\n";,
-    "#\n",
-    "# Unless required by applicable law or agreed to in writing, software\n",
-    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
-    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
implied.\n",
-    "# See the License for the specific language governing permissions and\n",
-    "# limitations under the License."
-   ],
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
    "id": "4d47e95ddd66c645"
   },
   {
@@ -114,8 +100,8 @@
       "Requirement already satisfied: referencing>=0.28.4 in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (from 
jsonschema>=3.0->altair<6,>=4.0->streamlit->burr[start]) (0.36.2)\n",
       "Requirement already satisfied: rpds-py>=0.7.1 in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (from 
jsonschema>=3.0->altair<6,>=4.0->streamlit->burr[start]) (0.24.0)\n",
       "\n",
-      
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m
 A new release of pip is available: 
\u001B[0m\u001B[31;49m24.3.1\u001B[0m\u001B[39;49m -> 
\u001B[0m\u001B[32;49m25.1\u001B[0m\n",
-      
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m
 To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\n",
+      
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m
 A new release of pip is available: 
\u001b[0m\u001b[31;49m24.3.1\u001b[0m\u001b[39;49m -> 
\u001b[0m\u001b[32;49m25.1\u001b[0m\n",
+      
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m
 To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n",
       "Requirement already satisfied: openai in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (1.75.0)\n",
       "Requirement already satisfied: anyio<5,>=3.5.0 in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (from openai) 
(4.9.0)\n",
       "Requirement already satisfied: distro<2,>=1.7.0 in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (from openai) 
(1.9.0)\n",
@@ -133,8 +119,8 @@
       "Requirement already satisfied: pydantic-core==2.33.1 in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (from 
pydantic<3,>=1.9.0->openai) (2.33.1)\n",
       "Requirement already satisfied: typing-inspection>=0.4.0 in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (from 
pydantic<3,>=1.9.0->openai) (0.4.0)\n",
       "\n",
-      
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m
 A new release of pip is available: 
\u001B[0m\u001B[31;49m24.3.1\u001B[0m\u001B[39;49m -> 
\u001B[0m\u001B[32;49m25.1\u001B[0m\n",
-      
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m
 To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\n",
+      
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m
 A new release of pip is available: 
\u001b[0m\u001b[31;49m24.3.1\u001b[0m\u001b[39;49m -> 
\u001b[0m\u001b[32;49m25.1\u001b[0m\n",
+      
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m
 To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n",
       "Requirement already satisfied: tavily-python in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (0.5.4)\n",
       "Requirement already satisfied: requests in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (from 
tavily-python) (2.32.3)\n",
       "Requirement already satisfied: tiktoken>=0.5.1 in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (from 
tavily-python) (0.9.0)\n",
@@ -150,8 +136,8 @@
       "Requirement already satisfied: sniffio>=1.1 in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (from 
anyio->httpx->tavily-python) (1.3.1)\n",
       "Requirement already satisfied: typing_extensions>=4.5 in 
/home/maggie/.pyenv/versions/3.12.9/lib/python3.12/site-packages (from 
anyio->httpx->tavily-python) (4.13.2)\n",
       "\n",
-      
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m
 A new release of pip is available: 
\u001B[0m\u001B[31;49m24.3.1\u001B[0m\u001B[39;49m -> 
\u001B[0m\u001B[32;49m25.1\u001B[0m\n",
-      
"\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m
 To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\n"
+      
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m
 A new release of pip is available: 
\u001b[0m\u001b[31;49m24.3.1\u001b[0m\u001b[39;49m -> 
\u001b[0m\u001b[32;49m25.1\u001b[0m\n",
+      
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m
 To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n"
      ]
     }
    ],
diff --git a/examples/deep-researcher/requirements.txt 
b/examples/deep-researcher/requirements.txt
index eb345e08..cc5dc625 100644
--- a/examples/deep-researcher/requirements.txt
+++ b/examples/deep-researcher/requirements.txt
@@ -1,16 +1,19 @@
-# Copyright 2026 Apache Software Foundation
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+#   http://www.apache.org/licenses/LICENSE-2.0
 #
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
 
 burr[start]
 openai
diff --git a/examples/deployment/vercel/README.md 
b/examples/deployment/vercel/README.md
index 13762fb3..3f1e3ed5 100644
--- a/examples/deployment/vercel/README.md
+++ b/examples/deployment/vercel/README.md
@@ -139,4 +139,4 @@ Check your Vercel Dashboard → Domains section for the 
correct URL.
 
 - [Vercel Documentation](https://vercel.com/docs)
 - [Vercel Python Runtime](https://vercel.com/docs/functions/runtimes/python)
-- [Vercel CLI Reference](https://vercel.com/docs/cli)
\ No newline at end of file
+- [Vercel CLI Reference](https://vercel.com/docs/cli)
diff --git a/examples/deployment/vercel/api/counter.py 
b/examples/deployment/vercel/api/counter.py
index fd4e53c3..dad85fa0 100644
--- a/examples/deployment/vercel/api/counter.py
+++ b/examples/deployment/vercel/api/counter.py
@@ -19,8 +19,9 @@
 Vercel Serverless Function for counter application
 Endpoint: /api/counter
 """
-from http.server import BaseHTTPRequestHandler
 import json
+from http.server import BaseHTTPRequestHandler
+
 from app import counter_app
 
 
@@ -39,11 +40,11 @@ class handler(BaseHTTPRequestHandler):
         """
         try:
             # Read request body
-            content_length = int(self.headers.get('Content-Length', 0))
+            content_length = int(self.headers.get("Content-Length", 0))
             body = self.rfile.read(content_length)
 
             # Parse JSON payload
-            data = json.loads(body.decode('utf-8'))
+            data = json.loads(body.decode("utf-8"))
 
             # Extract parameter (equivalent to Lambda's 
event["body"]["number"])
             count_up_to = int(data.get("number", 0))
@@ -59,7 +60,7 @@ class handler(BaseHTTPRequestHandler):
 
             # Return success response with serialized state
             self.send_json_response(200, state.serialize())
-            
+
         except json.JSONDecodeError:
             self.send_error_response(400, "Invalid JSON format")
         except ValueError as e:
@@ -70,6 +71,7 @@ class handler(BaseHTTPRequestHandler):
             # Log error for debugging
             print(f"Error in counter handler: {str(e)}")
             import traceback
+
             traceback.print_exc()
             self.send_error_response(500, "Internal server error")
 
@@ -102,16 +104,16 @@ class handler(BaseHTTPRequestHandler):
             data: Response data (dict, list, or any JSON-serializable object)
         """
         self.send_response(status_code)
-        self.send_header('Content-Type', 'application/json')
+        self.send_header("Content-Type", "application/json")
         self.end_headers()
-        
+
         if isinstance(data, (dict, list)):
             response_body = json.dumps(data, ensure_ascii=False)
         else:
             response_body = str(data)
-        
-        self.wfile.write(response_body.encode('utf-8'))
-    
+
+        self.wfile.write(response_body.encode("utf-8"))
+
     def send_error_response(self, status_code, message):
         """Send error response to client.
 
@@ -120,9 +122,8 @@ class handler(BaseHTTPRequestHandler):
             message: Error message string to include in response body
         """
         self.send_response(status_code)
-        self.send_header('Content-Type', 'application/json')
+        self.send_header("Content-Type", "application/json")
         self.end_headers()
-        
-        error_body = json.dumps({'error': message})
-        self.wfile.write(error_body.encode('utf-8'))
 
+        error_body = json.dumps({"error": message})
+        self.wfile.write(error_body.encode("utf-8"))
diff --git a/examples/deployment/vercel/app/counter_app.py 
b/examples/deployment/vercel/app/counter_app.py
index 06697427..c5fe9536 100644
--- a/examples/deployment/vercel/app/counter_app.py
+++ b/examples/deployment/vercel/app/counter_app.py
@@ -57,4 +57,3 @@ def application(count_up_to: int = 10) -> Application:
         .with_entrypoint("counter")
         .build()
     )
-
diff --git a/examples/email-assistant/notebook.ipynb 
b/examples/email-assistant/notebook.ipynb
index cbe0adfc..b8e423db 100644
--- a/examples/email-assistant/notebook.ipynb
+++ b/examples/email-assistant/notebook.ipynb
@@ -5,21 +5,7 @@
    "cell_type": "code",
    "outputs": [],
    "execution_count": null,
-   "source": [
-    "# Copyright 2026 Apache Software Foundation\n",
-    "#\n",
-    "# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
-    "# you may not use this file except in compliance with the License.\n",
-    "# You may obtain a copy of the License at\n",
-    "#\n",
-    "#     http://www.apache.org/licenses/LICENSE-2.0\n";,
-    "#\n",
-    "# Unless required by applicable law or agreed to in writing, software\n",
-    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
-    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
implied.\n",
-    "# See the License for the specific language governing permissions and\n",
-    "# limitations under the License."
-   ],
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
    "id": "b12d533ee9ffae9"
   },
   {
diff --git a/examples/email-assistant/requirements.txt 
b/examples/email-assistant/requirements.txt
index b86c64f5..5e8f6fc0 100644
--- a/examples/email-assistant/requirements.txt
+++ b/examples/email-assistant/requirements.txt
@@ -1,16 +1,19 @@
-# Copyright 2026 Apache Software Foundation
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+#   http://www.apache.org/licenses/LICENSE-2.0
 #
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
 
 burr[start]
 openai
diff --git a/examples/hamilton-integration/notebook.ipynb 
b/examples/hamilton-integration/notebook.ipynb
index f7f02164..763542b0 100644
--- a/examples/hamilton-integration/notebook.ipynb
+++ b/examples/hamilton-integration/notebook.ipynb
@@ -1,5 +1,12 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "code",
    "execution_count": 1,
diff --git a/examples/haystack-integration/notebook.ipynb 
b/examples/haystack-integration/notebook.ipynb
index d1067287..a96e78e5 100644
--- a/examples/haystack-integration/notebook.ipynb
+++ b/examples/haystack-integration/notebook.ipynb
@@ -1,5 +1,12 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "metadata": {},
diff --git a/examples/hello-world-counter/notebook.ipynb 
b/examples/hello-world-counter/notebook.ipynb
index e9296025..2a94846f 100644
--- a/examples/hello-world-counter/notebook.ipynb
+++ b/examples/hello-world-counter/notebook.ipynb
@@ -5,21 +5,7 @@
    "cell_type": "code",
    "outputs": [],
    "execution_count": null,
-   "source": [
-    "# Copyright 2026 Apache Software Foundation\n",
-    "#\n",
-    "# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
-    "# you may not use this file except in compliance with the License.\n",
-    "# You may obtain a copy of the License at\n",
-    "#\n",
-    "#     http://www.apache.org/licenses/LICENSE-2.0\n";,
-    "#\n",
-    "# Unless required by applicable law or agreed to in writing, software\n",
-    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
-    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
implied.\n",
-    "# See the License for the specific language governing permissions and\n",
-    "# limitations under the License."
-   ],
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
    "id": "62688b26eff3080f"
   },
   {
diff --git a/examples/image-telephone/notebook.ipynb 
b/examples/image-telephone/notebook.ipynb
index c6bf5d63..edf305f5 100644
--- a/examples/image-telephone/notebook.ipynb
+++ b/examples/image-telephone/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "r7i3uy9vk7",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "code",
    "execution_count": null,
diff --git a/examples/instructor-gemini-flash/notebook.ipynb 
b/examples/instructor-gemini-flash/notebook.ipynb
index 111eaa4d..580e0c8c 100644
--- a/examples/instructor-gemini-flash/notebook.ipynb
+++ b/examples/instructor-gemini-flash/notebook.ipynb
@@ -1,5 +1,12 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "metadata": {},
diff --git a/examples/llm-adventure-game/notebook.ipynb 
b/examples/llm-adventure-game/notebook.ipynb
index 79285703..1a29a223 100644
--- a/examples/llm-adventure-game/notebook.ipynb
+++ b/examples/llm-adventure-game/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "tg4hpkvciy",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "code",
    "execution_count": null,
diff --git a/examples/multi-agent-collaboration/hamilton/notebook.ipynb 
b/examples/multi-agent-collaboration/hamilton/notebook.ipynb
index e0977df8..e91d2d5f 100644
--- a/examples/multi-agent-collaboration/hamilton/notebook.ipynb
+++ b/examples/multi-agent-collaboration/hamilton/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "6sjcd7v1klw",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "a80d8df22739b896",
diff --git a/examples/multi-agent-collaboration/lcel/notebook.ipynb 
b/examples/multi-agent-collaboration/lcel/notebook.ipynb
index 506b0327..93e8d003 100644
--- a/examples/multi-agent-collaboration/lcel/notebook.ipynb
+++ b/examples/multi-agent-collaboration/lcel/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "ggdb8jqi277",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "a80d8df22739b896",
diff --git a/examples/multi-modal-chatbot/burr_demo.ipynb 
b/examples/multi-modal-chatbot/burr_demo.ipynb
index 5af9f21f..5f26a6f5 100644
--- a/examples/multi-modal-chatbot/burr_demo.ipynb
+++ b/examples/multi-modal-chatbot/burr_demo.ipynb
@@ -5,21 +5,7 @@
    "cell_type": "code",
    "outputs": [],
    "execution_count": null,
-   "source": [
-    "# Copyright 2026 Apache Software Foundation\n",
-    "#\n",
-    "# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
-    "# you may not use this file except in compliance with the License.\n",
-    "# You may obtain a copy of the License at\n",
-    "#\n",
-    "#     http://www.apache.org/licenses/LICENSE-2.0\n";,
-    "#\n",
-    "# Unless required by applicable law or agreed to in writing, software\n",
-    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
-    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
implied.\n",
-    "# See the License for the specific language governing permissions and\n",
-    "# limitations under the License."
-   ],
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
    "id": "f19821bfb84682cd"
   },
   {
@@ -720,21 +706,21 @@
      "evalue": "Demo error",
      "output_type": "error",
      "traceback": [
-      
"\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
-      "\u001B[0;31mValueError\u001B[0m                                
Traceback (most recent call last)",
-      "Cell \u001B[0;32mIn[4], line 5\u001B[0m\n\u001B[1;32m      3\u001B[0m 
\u001B[38;5;28;01mif\u001B[39;00m 
\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mquit\u001B[39m\u001B[38;5;124m\"\u001B[39m
 \u001B[38;5;241m==\u001B[39m 
user_input\u001B[38;5;241m.\u001B[39mlower():\n\u001B[1;32m      4\u001B[0m     
\u001B[38;5;28;01mbreak\u001B[39;00m\n\u001B[0;32m----> 5\u001B[0m last_action, 
action_result, app_state \u001B[38;5;241m=\u001B[39m 
\u001B[43mapp\u001B[49m\u001B[38;5;241;43m.\u001B[39 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/telemetry.py:276\u001B[0m, in 
\u001B[0;36mcapture_function_usage.<locals>.wrapped_fn\u001B[0;34m(*args, 
**kwargs)\u001B[0m\n\u001B[1;32m    273\u001B[0m 
\u001B[38;5;129m@functools\u001B[39m\u001B[38;5;241m.\u001B[39mwraps(call_fn)\n\u001B[1;32m
    274\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m 
\u001B[38;5;21mwrapped_fn\u001B[39m(\u001B[38;5;241m*\u001B[39margs, 
\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs):\n\u001B[1;32m    
27 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:616\u001B[0m, 
in 
\u001B[0;36m_call_execute_method_pre_post.__call__.<locals>.wrapper_sync\u001B[0;34m(app_self,
 *args, **kwargs)\u001B[0m\n\u001B[1;32m    614\u001B[0m exc 
\u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[1;32m   
 615\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 616\u001B[0m 
    \u001B[38;5;28;01mreturn\u001B[39;00m 
\u001B[43mfn\u001B[49m\u001B[43m(\u001B[49m\u001B[43m [...]
-      "File 
\u001B[0;32m~/dagworks/burr/burr/core/application.py:1168\u001B[0m, in 
\u001B[0;36mApplication.run\u001B[0;34m(self, halt_before, halt_after, 
inputs)\u001B[0m\n\u001B[1;32m   1166\u001B[0m 
\u001B[38;5;28;01mwhile\u001B[39;00m 
\u001B[38;5;28;01mTrue\u001B[39;00m:\n\u001B[1;32m   1167\u001B[0m     
\u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m-> 1168\u001B[0m         
\u001B[38;5;28;43mnext\u001B[39;49m\u001B[43m(\u001B[49m\u001B[43mgen\u001B[49m\u001B[43m)\u001B[49m\n\u001B[
 [...]
-      "File 
\u001B[0;32m~/dagworks/burr/burr/core/application.py:1111\u001B[0m, in 
\u001B[0;36mApplication.iterate\u001B[0;34m(self, halt_before, halt_after, 
inputs)\u001B[0m\n\u001B[1;32m   1108\u001B[0m prior_action: Optional[Action] 
\u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[1;32m   
1109\u001B[0m \u001B[38;5;28;01mwhile\u001B[39;00m 
\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mhas_next_action():\n\u001B[1;32m
   1110\u001B[0m     \u001B[38;5;66;0 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:616\u001B[0m, 
in 
\u001B[0;36m_call_execute_method_pre_post.__call__.<locals>.wrapper_sync\u001B[0;34m(app_self,
 *args, **kwargs)\u001B[0m\n\u001B[1;32m    614\u001B[0m exc 
\u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[1;32m   
 615\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 616\u001B[0m 
    \u001B[38;5;28;01mreturn\u001B[39;00m 
\u001B[43mfn\u001B[49m\u001B[43m(\u001B[49m\u001B[43m [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:773\u001B[0m, 
in \u001B[0;36mApplication.step\u001B[0;34m(self, 
inputs)\u001B[0m\n\u001B[1;32m    770\u001B[0m \u001B[38;5;66;03m# we need to 
increment the sequence before we start computing\u001B[39;00m\n\u001B[1;32m    
771\u001B[0m \u001B[38;5;66;03m# that way if we're replaying from state, we 
don't get stuck\u001B[39;00m\n\u001B[1;32m    772\u001B[0m 
\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_increment_sequ [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:826\u001B[0m, 
in \u001B[0;36mApplication._step\u001B[0;34m(self, inputs, 
_run_hooks)\u001B[0m\n\u001B[1;32m    824\u001B[0m     exc 
\u001B[38;5;241m=\u001B[39m e\n\u001B[1;32m    825\u001B[0m     
logger\u001B[38;5;241m.\u001B[39mexception(_format_BASE_ERROR_MESSAGE(next_action,
 \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_state, 
inputs))\n\u001B[0;32m--> 826\u001B[0m     \u001B[38;5;28;01mraise\u001B[39;00m 
e\n\ [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:812\u001B[0m, 
in \u001B[0;36mApplication._step\u001B[0;34m(self, inputs, 
_run_hooks)\u001B[0m\n\u001B[1;32m    810\u001B[0m 
\u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[1;32m    811\u001B[0m     
\u001B[38;5;28;01mif\u001B[39;00m 
next_action\u001B[38;5;241m.\u001B[39msingle_step:\n\u001B[0;32m--> 
812\u001B[0m         result, new_state \u001B[38;5;241m=\u001B[39m 
\u001B[43m_run_single_step_action\u001B[49m\u001B[43m(\u001B[49m [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/application.py:252\u001B[0m, 
in \u001B[0;36m_run_single_step_action\u001B[0;34m(action, state, 
inputs)\u001B[0m\n\u001B[1;32m    249\u001B[0m \u001B[38;5;66;03m# TODO -- 
guard all reads/writes with a subset of the state\u001B[39;00m\n\u001B[1;32m    
250\u001B[0m 
action\u001B[38;5;241m.\u001B[39mvalidate_inputs(inputs)\n\u001B[1;32m    
251\u001B[0m result, new_state \u001B[38;5;241m=\u001B[39m 
_adjust_single_step_output(\n\u001B[0;32m--> 2 [...]
-      "File \u001B[0;32m~/dagworks/burr/burr/core/action.py:639\u001B[0m, in 
\u001B[0;36mFunctionBasedAction.run_and_update\u001B[0;34m(self, state, 
**run_kwargs)\u001B[0m\n\u001B[1;32m    638\u001B[0m 
\u001B[38;5;28;01mdef\u001B[39;00m 
\u001B[38;5;21mrun_and_update\u001B[39m(\u001B[38;5;28mself\u001B[39m, state: 
State, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mrun_kwargs) 
\u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m 
\u001B[38;5;28mtuple\u001B[39m[\u001B[38;5;28mdic [...]
-      "Cell \u001B[0;32mIn[1], line 94\u001B[0m, in 
\u001B[0;36mimage_response\u001B[0;34m(state, model)\u001B[0m\n\u001B[1;32m     
91\u001B[0m 
\u001B[38;5;129m@action\u001B[39m(reads\u001B[38;5;241m=\u001B[39m[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mprompt\u001B[39m\u001B[38;5;124m\"\u001B[39m,
 
\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mchat_history\u001B[39m\u001B[38;5;124m\"\u001B[39m,
 
\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmode\u001B[39m\u001B[38;5;124m\"\u001B[39m],
 writes [...]
-      "\u001B[0;31mValueError\u001B[0m: Demo error"
+      
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mValueError\u001b[0m                                
Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[4], line 5\u001b[0m\n\u001b[1;32m      3\u001b[0m 
\u001b[38;5;28;01mif\u001b[39;00m 
\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mquit\u001b[39m\u001b[38;5;124m\"\u001b[39m
 \u001b[38;5;241m==\u001b[39m 
user_input\u001b[38;5;241m.\u001b[39mlower():\n\u001b[1;32m      4\u001b[0m     
\u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[0;32m----> 5\u001b[0m last_action, 
action_result, app_state \u001b[38;5;241m=\u001b[39m 
\u001b[43mapp\u001b[49m\u001b[38;5;241;43m.\u001b[39 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/telemetry.py:276\u001b[0m, in 
\u001b[0;36mcapture_function_usage.<locals>.wrapped_fn\u001b[0;34m(*args, 
**kwargs)\u001b[0m\n\u001b[1;32m    273\u001b[0m 
\u001b[38;5;129m@functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(call_fn)\n\u001b[1;32m
    274\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m 
\u001b[38;5;21mwrapped_fn\u001b[39m(\u001b[38;5;241m*\u001b[39margs, 
\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m    
27 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:616\u001b[0m, 
in 
\u001b[0;36m_call_execute_method_pre_post.__call__.<locals>.wrapper_sync\u001b[0;34m(app_self,
 *args, **kwargs)\u001b[0m\n\u001b[1;32m    614\u001b[0m exc 
\u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m   
 615\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 616\u001b[0m 
    \u001b[38;5;28;01mreturn\u001b[39;00m 
\u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[43m [...]
+      "File 
\u001b[0;32m~/dagworks/burr/burr/core/application.py:1168\u001b[0m, in 
\u001b[0;36mApplication.run\u001b[0;34m(self, halt_before, halt_after, 
inputs)\u001b[0m\n\u001b[1;32m   1166\u001b[0m 
\u001b[38;5;28;01mwhile\u001b[39;00m 
\u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m   1167\u001b[0m     
\u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1168\u001b[0m         
\u001b[38;5;28;43mnext\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mgen\u001b[49m\u001b[43m)\u001b[49m\n\u001b[
 [...]
+      "File 
\u001b[0;32m~/dagworks/burr/burr/core/application.py:1111\u001b[0m, in 
\u001b[0;36mApplication.iterate\u001b[0;34m(self, halt_before, halt_after, 
inputs)\u001b[0m\n\u001b[1;32m   1108\u001b[0m prior_action: Optional[Action] 
\u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m   
1109\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m 
\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhas_next_action():\n\u001b[1;32m
   1110\u001b[0m     \u001b[38;5;66;0 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:616\u001b[0m, 
in 
\u001b[0;36m_call_execute_method_pre_post.__call__.<locals>.wrapper_sync\u001b[0;34m(app_self,
 *args, **kwargs)\u001b[0m\n\u001b[1;32m    614\u001b[0m exc 
\u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m   
 615\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 616\u001b[0m 
    \u001b[38;5;28;01mreturn\u001b[39;00m 
\u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[43m [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:773\u001b[0m, 
in \u001b[0;36mApplication.step\u001b[0;34m(self, 
inputs)\u001b[0m\n\u001b[1;32m    770\u001b[0m \u001b[38;5;66;03m# we need to 
increment the sequence before we start computing\u001b[39;00m\n\u001b[1;32m    
771\u001b[0m \u001b[38;5;66;03m# that way if we're replaying from state, we 
don't get stuck\u001b[39;00m\n\u001b[1;32m    772\u001b[0m 
\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_increment_sequ [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:826\u001b[0m, 
in \u001b[0;36mApplication._step\u001b[0;34m(self, inputs, 
_run_hooks)\u001b[0m\n\u001b[1;32m    824\u001b[0m     exc 
\u001b[38;5;241m=\u001b[39m e\n\u001b[1;32m    825\u001b[0m     
logger\u001b[38;5;241m.\u001b[39mexception(_format_BASE_ERROR_MESSAGE(next_action,
 \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_state, 
inputs))\n\u001b[0;32m--> 826\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m 
e\n\ [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:812\u001b[0m, 
in \u001b[0;36mApplication._step\u001b[0;34m(self, inputs, 
_run_hooks)\u001b[0m\n\u001b[1;32m    810\u001b[0m 
\u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m    811\u001b[0m     
\u001b[38;5;28;01mif\u001b[39;00m 
next_action\u001b[38;5;241m.\u001b[39msingle_step:\n\u001b[0;32m--> 
812\u001b[0m         result, new_state \u001b[38;5;241m=\u001b[39m 
\u001b[43m_run_single_step_action\u001b[49m\u001b[43m(\u001b[49m [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/application.py:252\u001b[0m, 
in \u001b[0;36m_run_single_step_action\u001b[0;34m(action, state, 
inputs)\u001b[0m\n\u001b[1;32m    249\u001b[0m \u001b[38;5;66;03m# TODO -- 
guard all reads/writes with a subset of the state\u001b[39;00m\n\u001b[1;32m    
250\u001b[0m 
action\u001b[38;5;241m.\u001b[39mvalidate_inputs(inputs)\n\u001b[1;32m    
251\u001b[0m result, new_state \u001b[38;5;241m=\u001b[39m 
_adjust_single_step_output(\n\u001b[0;32m--> 2 [...]
+      "File \u001b[0;32m~/dagworks/burr/burr/core/action.py:639\u001b[0m, in 
\u001b[0;36mFunctionBasedAction.run_and_update\u001b[0;34m(self, state, 
**run_kwargs)\u001b[0m\n\u001b[1;32m    638\u001b[0m 
\u001b[38;5;28;01mdef\u001b[39;00m 
\u001b[38;5;21mrun_and_update\u001b[39m(\u001b[38;5;28mself\u001b[39m, state: 
State, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mrun_kwargs) 
\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m 
\u001b[38;5;28mtuple\u001b[39m[\u001b[38;5;28mdic [...]
+      "Cell \u001b[0;32mIn[1], line 94\u001b[0m, in 
\u001b[0;36mimage_response\u001b[0;34m(state, model)\u001b[0m\n\u001b[1;32m     
91\u001b[0m 
\u001b[38;5;129m@action\u001b[39m(reads\u001b[38;5;241m=\u001b[39m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mprompt\u001b[39m\u001b[38;5;124m\"\u001b[39m,
 
\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mchat_history\u001b[39m\u001b[38;5;124m\"\u001b[39m,
 
\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmode\u001b[39m\u001b[38;5;124m\"\u001b[39m],
 writes [...]
+      "\u001b[0;31mValueError\u001b[0m: Demo error"
      ]
     }
    ],
diff --git a/examples/multi-modal-chatbot/notebook.ipynb 
b/examples/multi-modal-chatbot/notebook.ipynb
index 53753899..87c0084a 100644
--- a/examples/multi-modal-chatbot/notebook.ipynb
+++ b/examples/multi-modal-chatbot/notebook.ipynb
@@ -5,21 +5,7 @@
    "cell_type": "code",
    "outputs": [],
    "execution_count": null,
-   "source": [
-    "# Copyright 2026 Apache Software Foundation\n",
-    "#\n",
-    "# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
-    "# you may not use this file except in compliance with the License.\n",
-    "# You may obtain a copy of the License at\n",
-    "#\n",
-    "#     http://www.apache.org/licenses/LICENSE-2.0\n";,
-    "#\n",
-    "# Unless required by applicable law or agreed to in writing, software\n",
-    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
-    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
implied.\n",
-    "# See the License for the specific language governing permissions and\n",
-    "# limitations under the License."
-   ],
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
    "id": "d1d5e86fb8bcd92f"
   },
   {
diff --git a/examples/multi-modal-chatbot/requirements.txt 
b/examples/multi-modal-chatbot/requirements.txt
index e2a2deb2..9064181f 100644
--- a/examples/multi-modal-chatbot/requirements.txt
+++ b/examples/multi-modal-chatbot/requirements.txt
@@ -1,16 +1,19 @@
-# Copyright 2026 Apache Software Foundation
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+#   http://www.apache.org/licenses/LICENSE-2.0
 #
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
 
 burr[streamlit,start]
 openai
diff --git a/examples/opentelemetry/notebook.ipynb 
b/examples/opentelemetry/notebook.ipynb
index f91424b0..d7800432 100644
--- a/examples/opentelemetry/notebook.ipynb
+++ b/examples/opentelemetry/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "xw8vgb7rav",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "code",
    "execution_count": 1,
diff --git a/examples/other-examples/cowsay/notebook.ipynb 
b/examples/other-examples/cowsay/notebook.ipynb
index 3cb4ee59..d4062c1f 100644
--- a/examples/other-examples/cowsay/notebook.ipynb
+++ b/examples/other-examples/cowsay/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "hm05ef0z1wg",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "code",
    "execution_count": null,
diff --git a/examples/parallelism/notebook.ipynb 
b/examples/parallelism/notebook.ipynb
index ac2f3391..5b150b22 100644
--- a/examples/parallelism/notebook.ipynb
+++ b/examples/parallelism/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "ibxhi2neov",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "f4b744ec-ce8d-4e6b-b818-d86f6a869028",
diff --git a/examples/rag-lancedb-ingestion/notebook.ipynb 
b/examples/rag-lancedb-ingestion/notebook.ipynb
index 06e719b1..5ee2ccae 100644
--- a/examples/rag-lancedb-ingestion/notebook.ipynb
+++ b/examples/rag-lancedb-ingestion/notebook.ipynb
@@ -1,5 +1,12 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "metadata": {},
diff --git a/examples/ray/notebook.ipynb b/examples/ray/notebook.ipynb
index e3f94ce5..616434d9 100644
--- a/examples/ray/notebook.ipynb
+++ b/examples/ray/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "srtl3nofyb",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "a24201eb-2541-4ef1-bed2-14f34fe37ae7",
diff --git a/examples/recursive/notebook.ipynb 
b/examples/recursive/notebook.ipynb
index c1d33d58..e71ce7fc 100644
--- a/examples/recursive/notebook.ipynb
+++ b/examples/recursive/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "i224d87jsmn",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "4bb251de-463e-4156-bcfc-9078721f6a8b",
diff --git a/examples/simple-chatbot-intro/notebook.ipynb 
b/examples/simple-chatbot-intro/notebook.ipynb
index 5fa24b11..93ba520a 100644
--- a/examples/simple-chatbot-intro/notebook.ipynb
+++ b/examples/simple-chatbot-intro/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "ripueq9wwyn",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "61278d3e-958b-49ee-94b8-2ee1f5e58773",
diff --git a/examples/streaming-fastapi/notebook.ipynb 
b/examples/streaming-fastapi/notebook.ipynb
index a4a813ee..fcb411c4 100644
--- a/examples/streaming-fastapi/notebook.ipynb
+++ b/examples/streaming-fastapi/notebook.ipynb
@@ -5,21 +5,7 @@
    "cell_type": "code",
    "outputs": [],
    "execution_count": null,
-   "source": [
-    "# Copyright 2026 Apache Software Foundation\n",
-    "#\n",
-    "# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
-    "# you may not use this file except in compliance with the License.\n",
-    "# You may obtain a copy of the License at\n",
-    "#\n",
-    "#     http://www.apache.org/licenses/LICENSE-2.0\n";,
-    "#\n",
-    "# Unless required by applicable law or agreed to in writing, software\n",
-    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
-    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
implied.\n",
-    "# See the License for the specific language governing permissions and\n",
-    "# limitations under the License."
-   ],
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
    "id": "8b8a0b32aa99226c"
   },
   {
diff --git a/examples/streaming-overview/notebook.ipynb 
b/examples/streaming-overview/notebook.ipynb
index 9319361b..0634b2b6 100644
--- a/examples/streaming-overview/notebook.ipynb
+++ b/examples/streaming-overview/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "j77l9jka9",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "code",
    "execution_count": null,
diff --git a/examples/talks/data_for_ai_oct_2024.ipynb 
b/examples/talks/data_for_ai_oct_2024.ipynb
index f5134928..49eb22f6 100644
--- a/examples/talks/data_for_ai_oct_2024.ipynb
+++ b/examples/talks/data_for_ai_oct_2024.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "1xkfukqa5p7",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "f27c0e174c8ee037",
diff --git a/examples/test-case-creation/notebook.ipynb 
b/examples/test-case-creation/notebook.ipynb
index d37d6ad0..61e1064a 100644
--- a/examples/test-case-creation/notebook.ipynb
+++ b/examples/test-case-creation/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "wj2m4qtpx1e",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "code",
    "execution_count": null,
diff --git a/examples/tool-calling/notebook.ipynb 
b/examples/tool-calling/notebook.ipynb
index 43689269..eb6b47b8 100644
--- a/examples/tool-calling/notebook.ipynb
+++ b/examples/tool-calling/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "8ps8bnh6lo3",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "5eebfc21-b54a-435d-84dc-b9de1d620e4e",
diff --git a/examples/tracing-and-spans/burr_otel_demo.ipynb 
b/examples/tracing-and-spans/burr_otel_demo.ipynb
index bbb87458..918acb85 100644
--- a/examples/tracing-and-spans/burr_otel_demo.ipynb
+++ b/examples/tracing-and-spans/burr_otel_demo.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "m7797lu1xm",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "f63df3e4b8d4fdba",
diff --git a/examples/tracing-and-spans/notebook.ipynb 
b/examples/tracing-and-spans/notebook.ipynb
index bb69850e..f4bff96d 100644
--- a/examples/tracing-and-spans/notebook.ipynb
+++ b/examples/tracing-and-spans/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "xfdmdmo8t2b",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "code",
    "execution_count": null,
diff --git a/examples/typed-state/notebook.ipynb 
b/examples/typed-state/notebook.ipynb
index bd14801e..38cd8bba 100644
--- a/examples/typed-state/notebook.ipynb
+++ b/examples/typed-state/notebook.ipynb
@@ -1,5 +1,13 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "id": "x6ta2gzvqv",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "id": "8419f04e-f945-491d-9526-6aebbabbad6a",
diff --git a/examples/youtube-to-social-media-post/notebook.ipynb 
b/examples/youtube-to-social-media-post/notebook.ipynb
index cacaac34..a7aed43b 100644
--- a/examples/youtube-to-social-media-post/notebook.ipynb
+++ b/examples/youtube-to-social-media-post/notebook.ipynb
@@ -1,5 +1,12 @@
 {
  "cells": [
+  {
+   "cell_type": "code",
+   "source": "# Licensed to the Apache Software Foundation (ASF) under one\n# 
or more contributor license agreements.  See the NOTICE file\n# distributed 
with this work for additional information\n# regarding copyright ownership.  
The ASF licenses this file\n# to you under the Apache License, Version 2.0 
(the\n# \"License\"); you may not use this file except in compliance\n# with 
the License.  You may obtain a copy of the License at\n#\n#   
http://www.apache.org/licenses/LICENSE-2.0\n#\n [...]
+   "metadata": {},
+   "execution_count": null,
+   "outputs": []
+  },
   {
    "cell_type": "markdown",
    "metadata": {},
diff --git a/pyproject.toml b/pyproject.toml
index 7b8da0fa..e88dce53 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -21,7 +21,7 @@ build-backend = "flit_core.buildapi"
 
 [project]
 name = "apache-burr"
-version = "0.40.2"
+version = "0.41.0"
 dependencies = [] # yes, there are none
 requires-python = ">=3.9"
 authors = [
@@ -32,22 +32,7 @@ maintainers = [
   {name = "Elijah ben Izzy", email = "[email protected]"},
   {name = "Stefan Krawczyk", email = "[email protected]"},
 ]
-description = """Apache Burr (incubating) makes it easy to develop 
applications that make decisions (chatbots, agents, simulations, etc...) from 
simple python building blocks.
-
-Apache Burr works well for any application that uses LLMs, and can integrate 
with any of your favorite frameworks. Burr includes a UI that can 
track/monitor/trace your system in real time, along with
-pluggable persisters (e.g. for memory) to save & load application state.
-
-Apache Burr (incubating) is an effort undergoing incubation at the Apache
-Software Foundation (ASF), sponsored by the Apache Incubator PMC.
-
-Incubation is required of all newly accepted projects until a further review
-indicates that the infrastructure, communications, and decision making process
-have stabilized in a manner consistent with other successful ASF projects.
-
-While incubation status is not necessarily a reflection of the completeness
-or stability of the code, it does indicate that the project has yet to be
-fully endorsed by the ASF.
-"""
+description = "Apache Burr (incubating) makes it easy to develop applications 
that make decisions (chatbots, agents, simulations, etc...) from simple python 
building blocks."
 readme = "README.md"
 license-files = ["LICENSE", "NOTICE", "DISCLAIMER"]
 keywords = ["mlops", "data", "state-machine", "llmops"]
diff --git a/scripts/README.md b/scripts/README.md
index 867c58f1..3a07b126 100644
--- a/scripts/README.md
+++ b/scripts/README.md
@@ -54,6 +54,7 @@ Specifically, we set the following guidelines:
 Prerequisites:
 - Python 3.9+
 - `flit` for building (`pip install flit`)
+- `twine` for package validation (`pip install twine`)
 - GPG key configured for signing
 - Node.js + npm for UI builds
 - Apache RAT jar for license checking (optional)
@@ -97,7 +98,7 @@ python scripts/apache_release.py verify 0.41.0 0
 python scripts/apache_release.py all 0.41.0 0 your_apache_id --no-upload
 ```
 
-Output: `dist/` directory with tar.gz (archive + sdist), whl, plus .asc and 
.sha512 files. Install from the whl file to test it out after runnig the 
`wheel` subcommand.
+Output: `dist/` directory with tar.gz (archive + sdist), whl, plus .asc and 
.sha512 files. The wheel is validated with `twine check` to ensure metadata 
correctness before signing. Install from the whl file to test it out after 
running the `wheel` subcommand.
 
 ## For Voters: Verifying a Release
 
@@ -119,7 +120,7 @@ wget https://downloads.apache.org/incubator/burr/KEYS
 gpg --import KEYS
 
 # Verify git archive signature
-gpg --verify apache-burr-${VERSION}-incubating.tar.gz.asc 
apache-burr-${VERSION}-incubating.tar.gz
+gpg --verify apache-burr-${VERSION}-incubating-src.tar.gz.asc 
apache-burr-${VERSION}-incubating-src.tar.gz
 
 # Verify sdist signature
 gpg --verify apache-burr-${VERSION}-incubating-sdist.tar.gz.asc 
apache-burr-${VERSION}-incubating-sdist.tar.gz
@@ -128,13 +129,13 @@ gpg --verify 
apache-burr-${VERSION}-incubating-sdist.tar.gz.asc apache-burr-${VE
 gpg --verify apache_burr-${VERSION}-py3-none-any.whl.asc 
apache_burr-${VERSION}-py3-none-any.whl
 
 # 3. Verify all SHA512 checksums
-echo "$(cat apache-burr-${VERSION}-incubating.tar.gz.sha512)  
apache-burr-${VERSION}-incubating.tar.gz" | sha512sum -c -
+echo "$(cat apache-burr-${VERSION}-incubating-src.tar.gz.sha512)  
apache-burr-${VERSION}-incubating-src.tar.gz" | sha512sum -c -
 echo "$(cat apache-burr-${VERSION}-incubating-sdist.tar.gz.sha512)  
apache-burr-${VERSION}-incubating-sdist.tar.gz" | sha512sum -c -
 echo "$(cat apache_burr-${VERSION}-py3-none-any.whl.sha512)  
apache_burr-${VERSION}-py3-none-any.whl" | sha512sum -c -
 
 # 4. Extract the source archive
-tar -xzf apache-burr-${VERSION}-incubating.tar.gz
-cd apache-burr-${VERSION}-incubating/
+tar -xzf apache-burr-${VERSION}-incubating-src.tar.gz
+cd apache-burr-${VERSION}-incubating-src/
 
 # 5. Install build dependencies
 pip install flit
@@ -215,7 +216,7 @@ python scripts/verify_apache_artifacts.py licenses 
--rat-jar apache-rat-0.15.jar
 python scripts/verify_apache_artifacts.py all --rat-jar apache-rat-0.15.jar
 
 # Inspect artifact contents
-python scripts/verify_apache_artifacts.py list-contents 
dist/apache-burr-0.41.0.tar.gz
+python scripts/verify_apache_artifacts.py list-contents 
dist/apache-burr-0.41.0-incubating-src.tar.gz
 python scripts/verify_apache_artifacts.py list-contents 
dist/apache_burr-0.41.0-py3-none-any.whl
 ```
 
diff --git a/scripts/apache_release.py b/scripts/apache_release.py
index d4c28afc..0c355ba6 100644
--- a/scripts/apache_release.py
+++ b/scripts/apache_release.py
@@ -134,10 +134,10 @@ def _validate_environment_for_command(args) -> None:
     command_requirements = {
         "archive": ["git", "gpg"],
         "sdist": ["git", "gpg", "flit"],
-        "wheel": ["git", "gpg", "flit", "node", "npm"],
+        "wheel": ["git", "gpg", "flit", "node", "npm", "twine"],
         "upload": ["git", "gpg", "svn"],
-        "all": ["git", "gpg", "flit", "node", "npm", "svn"],
-        "verify": ["git", "gpg"],
+        "all": ["git", "gpg", "flit", "node", "npm", "svn", "twine"],
+        "verify": ["git", "gpg", "twine"],
     }
 
     required_tools = command_requirements.get(args.command, ["git", "gpg"])
@@ -165,6 +165,8 @@ def _validate_environment_for_command(args) -> None:
         for tool in missing_tools:
             if tool == "flit":
                 print(f"  • {tool}: Install with 'pip install flit'")
+            elif tool == "twine":
+                print(f"  • {tool}: Install with 'pip install twine'")
             elif tool in ["node", "npm"]:
                 print(f"  • {tool}: Install from https://nodejs.org/";)
             else:
@@ -341,9 +343,9 @@ def _create_git_archive(version: str, rc_num: str, 
output_dir: str = "dist") ->
 
     os.makedirs(output_dir, exist_ok=True)
 
-    archive_name = f"apache-burr-{version}-incubating.tar.gz"
+    archive_name = f"apache-burr-{version}-incubating-src.tar.gz"
     archive_path = os.path.join(output_dir, archive_name)
-    prefix = f"apache-burr-{version}-incubating/"
+    prefix = f"apache-burr-{version}-incubating-src/"
 
     _run_command(
         [
@@ -616,6 +618,30 @@ def _verify_wheel(wheel_path: str) -> bool:
         return False
 
 
+def _verify_wheel_with_twine(wheel_path: str) -> bool:
+    """Verify wheel metadata and package validity using twine."""
+    print(f"  Verifying wheel with twine: {os.path.basename(wheel_path)}")
+
+    try:
+        subprocess.run(
+            ["twine", "check", wheel_path],
+            check=True,
+            capture_output=True,
+            text=True,
+        )
+        print("    ✓ Twine check passed")
+        print("    ✓ Wheel metadata is valid")
+        return True
+    except subprocess.CalledProcessError as e:
+        print("\n❌ Twine metadata validation failed\n")
+        print("Twine output:")
+        if e.stdout:
+            print(e.stdout)
+        if e.stderr:
+            print(e.stderr)
+        _fail("Wheel failed twine validation - see output above for details")
+
+
 # ============================================================================
 # Upload to Apache SVN
 # ============================================================================
@@ -786,13 +812,17 @@ def cmd_wheel(args) -> bool:
 
     wheel_path = _build_wheel_from_current_dir(args.version, args.output_dir)
 
-    print("\nSigning wheel...")
-    _sign_artifact(wheel_path)
+    print("\nVerifying wheel with twine...")
+    if not _verify_wheel_with_twine(wheel_path):
+        _fail("Twine verification failed!")
 
-    print("\nVerifying wheel...")
+    print("\nVerifying wheel contents...")
     if not _verify_wheel(wheel_path):
         _fail("Wheel verification failed!")
 
+    print("\nSigning wheel...")
+    _sign_artifact(wheel_path)
+
     if not _verify_artifact_complete(wheel_path):
         _fail("Wheel signature/checksum verification failed!")
 
@@ -872,6 +902,8 @@ def cmd_all(args) -> bool:
     # Step 3: Build wheel
     _print_step(3, 4, "Building wheel")
     wheel_path = _build_wheel_from_current_dir(args.version, args.output_dir)
+    if not _verify_wheel_with_twine(wheel_path):
+        _fail("Twine verification failed!")
     _sign_artifact(wheel_path)
     if not _verify_wheel(wheel_path) or not 
_verify_artifact_complete(wheel_path):
         _fail("Wheel verification failed!")
diff --git a/scripts/verify_apache_artifacts.py 
b/scripts/verify_apache_artifacts.py
index f4861d32..54350deb 100755
--- a/scripts/verify_apache_artifacts.py
+++ b/scripts/verify_apache_artifacts.py
@@ -24,7 +24,7 @@ Checks signatures, checksums, licenses, and archive integrity.
 
 Usage:
     # List contents of an artifact
-    python scripts/verify_apache_artifacts.py list-contents 
dist/apache-burr-0.41.0.tar.gz
+    python scripts/verify_apache_artifacts.py list-contents 
dist/apache-burr-0.41.0-incubating-src.tar.gz
 
     # Verify signatures and checksums
     python scripts/verify_apache_artifacts.py signatures
@@ -40,6 +40,7 @@ Usage:
 """
 
 import argparse
+import glob
 import hashlib
 import os
 import shutil
@@ -610,6 +611,35 @@ def cmd_list_contents(args) -> None:
     list_contents(args.artifact)
 
 
+def cmd_twine_check(args) -> bool:
+    """Verify wheel metadata with twine."""
+    _print_section("Verifying Wheel Metadata with Twine")
+
+    wheel_pattern = f"{args.artifacts_dir}/apache_burr-*.whl"
+    wheel_files = glob.glob(wheel_pattern)
+
+    if not wheel_files:
+        print(f"❌ No wheel found matching: {wheel_pattern}")
+        return False
+
+    for wheel_path in wheel_files:
+        print(f"\nChecking {os.path.basename(wheel_path)}...")
+        try:
+            subprocess.run(
+                ["twine", "check", wheel_path],
+                check=True,
+                capture_output=True,
+                text=True,
+            )
+            print(f"  ✓ {os.path.basename(wheel_path)} metadata is valid")
+        except subprocess.CalledProcessError as e:
+            print(f"  ✗ Twine check failed: {e.stderr}")
+            return False
+
+    print("\n✅ All wheels passed twine validation")
+    return True
+
+
 # ============================================================================
 # CLI Entry Point
 # ============================================================================
@@ -623,7 +653,7 @@ def main():
         epilog="""
 Examples:
   # List contents of a specific artifact
-  python scripts/verify_apache_artifacts.py list-contents 
dist/apache-burr-0.41.0.tar.gz
+  python scripts/verify_apache_artifacts.py list-contents 
dist/apache-burr-0.41.0-incubating-src.tar.gz
   python scripts/verify_apache_artifacts.py list-contents 
dist/apache_burr-0.41.0-py3-none-any.whl
 
   # Verify signatures and checksums only
@@ -683,6 +713,12 @@ Examples:
         help="Generate report but don't fail on license issues",
     )
 
+    # twine-check subcommand
+    twine_parser = subparsers.add_parser("twine-check", help="Verify wheel 
metadata with twine")
+    twine_parser.add_argument(
+        "--artifacts-dir", default="dist", help="Directory containing 
artifacts (default: dist)"
+    )
+
     args = parser.parse_args()
 
     # Dispatch to command handler
@@ -697,6 +733,8 @@ Examples:
             success = cmd_licenses(args)
         elif args.command == "all":
             success = cmd_all(args)
+        elif args.command == "twine-check":
+            success = cmd_twine_check(args)
         else:
             _fail(f"Unknown command: {args.command}")
     except KeyboardInterrupt:
diff --git a/setup.cfg b/setup.cfg
index 82e5f051..60ee3500 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,16 +1,19 @@
-# Copyright 2026 Apache Software Foundation
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+#   http://www.apache.org/licenses/LICENSE-2.0
 #
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
 
 [flake8]
 max-line-length = 100
diff --git a/telemetry/ui/.eslintignore b/telemetry/ui/.eslintignore
index 57014ff7..cdfef607 100644
--- a/telemetry/ui/.eslintignore
+++ b/telemetry/ui/.eslintignore
@@ -1,16 +1,19 @@
-# Copyright 2026 Apache Software Foundation
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+#   http://www.apache.org/licenses/LICENSE-2.0
 #
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
 
 build/*
 tailwind.config.js
diff --git a/telemetry/ui/.prettierignore b/telemetry/ui/.prettierignore
index 86da4dbd..db8314b5 100644
--- a/telemetry/ui/.prettierignore
+++ b/telemetry/ui/.prettierignore
@@ -1,16 +1,19 @@
-# Copyright 2026 Apache Software Foundation
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+#   http://www.apache.org/licenses/LICENSE-2.0
 #
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
 
 build/*
 tailwind.config.js
diff --git a/telemetry/ui/public/robots.txt b/telemetry/ui/public/robots.txt
index d6fb2767..dc045698 100644
--- a/telemetry/ui/public/robots.txt
+++ b/telemetry/ui/public/robots.txt
@@ -1,16 +1,19 @@
-# Copyright 2026 Apache Software Foundation
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+#   http://www.apache.org/licenses/LICENSE-2.0
 #
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
 
 # https://www.robotstxt.org/robotstxt.html
 User-agent: *
diff --git a/tests/integrations/serde/test_pandas.py 
b/tests/integrations/serde/test_pandas.py
index 0bb01869..90879052 100644
--- a/tests/integrations/serde/test_pandas.py
+++ b/tests/integrations/serde/test_pandas.py
@@ -15,6 +15,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
+import os
+
 import pandas as pd
 
 from burr.core import serde, state
@@ -26,10 +28,16 @@ def test_serde_of_pandas_dataframe(tmp_path):
     serialized = og.serialize(pandas_kwargs={"path": tmp_path})
     assert serialized["df"][serde.KEY] == "pandas.DataFrame"
     assert serialized["df"]["path"].startswith(str(tmp_path))
-    assert (
-        
"df_a23d165ed4a2b8c6ccf24ac6276e35a9dc312e2828b4d0810416f4d47c614c7f.parquet"
-        in serialized["df"]["path"]
-    )
+
+    # Verify filename pattern instead of exact hash (hash may change with 
pandas versions)
+    filename = os.path.basename(serialized["df"]["path"])
+    assert filename.startswith("df_")
+    assert filename.endswith(".parquet")
+    # Verify it's a valid SHA256 hash (64 hex characters)
+    hash_part = filename[3:-8]  # Remove 'df_' prefix and '.parquet' suffix
+    assert len(hash_part) == 64
+    assert all(c in "0123456789abcdef" for c in hash_part)
+
     ng = state.State.deserialize(serialized, pandas_kwargs={"path": tmp_path})
     assert isinstance(ng["df"], pd.DataFrame)
     pd.testing.assert_frame_equal(ng["df"], df)

Reply via email to