A node that wraps a Python sync/async function or generator. Type coercions applied to function parameters (via ``TypeAdapter``): - ``dict`` → ``BaseModel`` when the annotation is a Pydantic model. - ``list[dict]`` → ``list[BaseModel]``, ``dict[K, dict]`` → ``dict[K, BaseModel]``, e
| 129 | |
| 130 | |
| 131 | class FunctionNode(BaseNode): |
| 132 | """A node that wraps a Python sync/async function or generator. |
| 133 | |
| 134 | Type coercions applied to function parameters (via ``TypeAdapter``): |
| 135 | - ``dict`` → ``BaseModel`` when the annotation is a Pydantic model. |
| 136 | - ``list[dict]`` → ``list[BaseModel]``, ``dict[K, dict]`` → |
| 137 | ``dict[K, BaseModel]``, etc. |
| 138 | - ``types.Content`` → ``str`` when the annotation expects ``str`` |
| 139 | (including ``Optional[str]`` / ``Union[str, ...]``). |
| 140 | - All other values are validated/coerced by Pydantic's ``TypeAdapter``. |
| 141 | """ |
| 142 | |
| 143 | auth_config: AuthConfig | None = None |
| 144 | """If set, the framework requests user authentication before running. |
| 145 | |
| 146 | When the node runs for the first time and no credential is found in |
| 147 | session state, it yields an ``adk_request_credential`` event and |
| 148 | interrupts. On resume, the credential is stored and the node |
| 149 | re-runs with the credential available via |
| 150 | ``AuthHandler(auth_config).get_auth_response(ctx.state)``. |
| 151 | """ |
| 152 | |
| 153 | parameter_binding: Literal['state', 'node_input'] = 'state' |
| 154 | """How function parameters are bound. |
| 155 | |
| 156 | ``'state'`` (default) binds parameters from ``ctx.state``. |
| 157 | ``'node_input'`` binds parameters from ``node_input`` dict and infers |
| 158 | ``input_schema`` / ``output_schema`` from the function signature |
| 159 | (used when the node acts as an agent's tool). |
| 160 | """ |
| 161 | |
| 162 | # Private attributes (won't be serialized) |
| 163 | _func: Callable[..., Any] = PrivateAttr() |
| 164 | _sig: inspect.Signature = PrivateAttr() |
| 165 | _type_hints: dict[str, Any] = PrivateAttr() |
| 166 | _type_adapters: dict[str, TypeAdapter] = PrivateAttr() |
| 167 | _context_param_name: str | None = PrivateAttr(default=None) |
| 168 | |
| 169 | def __init__( |
| 170 | self, |
| 171 | *, |
| 172 | func: Callable[..., Any], |
| 173 | name: str | None = None, |
| 174 | rerun_on_resume: bool = False, |
| 175 | retry_config: RetryConfig | None = None, |
| 176 | timeout: float | None = None, |
| 177 | auth_config: AuthConfig | None = None, |
| 178 | parameter_binding: Literal['state', 'node_input'] = 'state', |
| 179 | state_schema: type[BaseModel] | None = None, |
| 180 | ): |
| 181 | """Initializes FunctionNode. |
| 182 | |
| 183 | Args: |
| 184 | func: A sync/async function or sync/async generator function that forms |
| 185 | the node's logic. It can accept 'ctx: Context' and 'node_input: Any' as |
| 186 | arguments, depending on its signature. If the function is not a |
| 187 | generator, its return value will be wrapped in an Event, unless the |
| 188 | return value is None. |
no outgoing calls