1919from collections .abc import AsyncGenerator
2020from collections .abc import Callable
2121from typing import Any
22+ from typing import Literal
2223from typing import overload
2324from typing import TYPE_CHECKING
2425from typing import TypeVar
3839 from ..agents .context import Context
3940 from ..auth .auth_tool import AuthConfig
4041
41- T = TypeVar ("T" , bound = Callable [..., Any ])
42+ T = TypeVar ('T' , bound = Callable [..., Any ])
4243
4344
4445@overload
@@ -50,6 +51,7 @@ def node(
5051 timeout : float | None = None ,
5152 parallel_worker : bool = False ,
5253 auth_config : AuthConfig | None = None ,
54+ parameter_binding : Literal ['state' , 'node_input' ] = 'state' ,
5355) -> Callable [
5456 [T ], function_node .FunctionNode | parallel_worker_lib ._ParallelWorker
5557]:
@@ -66,6 +68,7 @@ def node(
6668 timeout : float | None = None ,
6769 parallel_worker : bool = False ,
6870 auth_config : AuthConfig | None = None ,
71+ parameter_binding : Literal ['state' , 'node_input' ] = 'state' ,
6972) -> base_node .BaseNode :
7073 ...
7174
@@ -79,6 +82,7 @@ def node(
7982 timeout : float | None = None ,
8083 parallel_worker : bool = False ,
8184 auth_config : AuthConfig | None = None ,
85+ parameter_binding : Literal ['state' , 'node_input' ] = 'state' ,
8286) -> Any :
8387 """Decorator or function to wrap a NodeLike in a node or override its properties.
8488
@@ -107,6 +111,11 @@ async def my_func3(): ...
107111 parallel_worker: If True, wraps the node in a _ParallelWorker.
108112 auth_config: If provided, the framework requests user authentication
109113 before running the node. Requires rerun_on_resume=True.
114+ parameter_binding: How function parameters are bound. ``'state'``
115+ (default) binds parameters from ``ctx.state``. ``'node_input'``
116+ binds parameters from ``node_input`` dict and infers
117+ ``input_schema`` / ``output_schema`` from the function signature
118+ (used when the node acts as an agent's tool).
110119
111120 Returns:
112121 If used as a decorator factory (@node() or @node(...)), returns a decorator.
@@ -126,6 +135,7 @@ def wrapper(
126135 retry_config = retry_config ,
127136 timeout = timeout ,
128137 auth_config = auth_config ,
138+ parameter_binding = parameter_binding ,
129139 )
130140 if parallel_worker :
131141 return parallel_worker_lib ._ParallelWorker (node = built_node )
@@ -142,6 +152,7 @@ def wrapper(
142152 retry_config = retry_config ,
143153 timeout = timeout ,
144154 auth_config = auth_config ,
155+ parameter_binding = parameter_binding ,
145156 )
146157 if parallel_worker :
147158 return parallel_worker_lib ._ParallelWorker (node = built_node )
@@ -166,7 +177,7 @@ def model_post_init(self, __context: Any) -> None:
166177 # to avoid infinite recursion when its run() method is called.
167178 # The cloned node preserves the class identity and behavior of the
168179 # original (essential for LlmAgent and Workflow subclasses).
169- worker_node = self .model_copy (update = {" parallel_worker" : False })
180+ worker_node = self .model_copy (update = {' parallel_worker' : False })
170181
171182 inner = parallel_worker_lib ._ParallelWorker (node = worker_node )
172183 self ._inner_node = inner
@@ -181,7 +192,7 @@ def model_copy(
181192 copied = super ().model_copy (update = update , deep = deep )
182193
183194 if copied .parallel_worker :
184- worker_node = copied .model_copy (update = {" parallel_worker" : False })
195+ worker_node = copied .model_copy (update = {' parallel_worker' : False })
185196 copied ._inner_node = parallel_worker_lib ._ParallelWorker (node = worker_node )
186197 copied .rerun_on_resume = copied ._inner_node .rerun_on_resume
187198
@@ -195,7 +206,7 @@ async def run_node_impl(
195206 Subclasses can directly benefit from advanced flags like parallel_worker
196207 by providing their custom execution logic here.
197208 """
198- raise NotImplementedError (" run_node_impl must be implemented." )
209+ raise NotImplementedError (' run_node_impl must be implemented.' )
199210 yield
200211
201212 @override
@@ -205,7 +216,7 @@ async def _run_impl(
205216 """Dispatches to run_node_impl() or parallel_worker inner node."""
206217 if self .parallel_worker :
207218 if self ._inner_node is None :
208- raise ValueError (" inner_node is not initialized for parallel worker." )
219+ raise ValueError (' inner_node is not initialized for parallel worker.' )
209220 async for output in self ._inner_node .run (ctx = ctx , node_input = node_input ):
210221 yield output
211222 else :
0 commit comments