Skip to content

Inject Runtime into tools #5990

@sydney-runkle

Description

@sydney-runkle

Privileged issue

  • I am a LangGraph maintainer, or was asked directly by a LangGraph maintainer to create an issue here.

Issue Content

Right now, tools managed in ToolNode support the injection of things like config, state, store. We should also support the injection of Runtime from langgraph.runtime.

Ideally we wouldn't have to do the Annotated[runtime, InjectedRuntime] stuff bc that's pretty verbose.

Agent Context { "tasks": [ { "id": "b94a1a5d-3d18-4cb8-a586-1800e236aaec", "taskIndex": 0, "request": "[original issue]\n**Inject Runtime into tools**\n### Privileged issue\n\n- [x] I am a LangGraph maintainer, or was asked directly by a LangGraph maintainer to create an issue here.\n\n### Issue Content\n\nRight now, tools managed in `ToolNode` support the injection of things like config, state, store. We should also support the injection of `Runtime` from langgraph.runtime.\n\nIdeally we wouldn't have to do the `Annotated[runtime, InjectedRuntime]` stuff bc that's pretty verbose.", "title": "Add Runtime injection support to ToolNode for LangGraph tools", "createdAt": 1755864331842, "completed": true, "planRevisions": [ { "revisionIndex": 0, "plans": [ { "index": 0, "plan": "**Implement InjectedRuntime class and runtime injection logic in tool_node.py**\n- Add `InjectedRuntime` class after `InjectedStore` class (around line 950 in `libs/prebuilt/langgraph/prebuilt/tool_node.py`)\n- Add `_get_runtime_arg()` function after `_get_store_arg()` (around line 1100) to detect runtime injection requirements\n- Add `tool_to_runtime_arg` dict to ToolNode.__init__ (line ~342) to track which tools need runtime injection\n- Add `_inject_runtime()` method after `_inject_store()` (around line 665) to inject runtime from config into tool calls\n- Update `inject_tool_args()` method (line ~713) to call `_inject_runtime()` after `_inject_store()`\n- Import necessary dependencies: `CONF`, `CONFIG_KEY_RUNTIME` from `langgraph._internal._constants`", "completed": true, "summary": "Successfully implemented runtime injection support in tool_node.py:\n\n1. **Added imports**: Imported `CONF`, `CONFIG_KEY_RUNTIME` from `langgraph._internal._constants` and `Runtime` from `langgraph.runtime`\n\n2. **Created InjectedRuntime class**: Added a new `InjectedRuntime` class (lines 1006-1078) that inherits from `InjectedToolArg`, following the same pattern as `InjectedState` and `InjectedStore`. The class includes comprehensive documentation and examples.\n\n3. **Added _get_runtime_arg function**: Implemented `_get_runtime_arg()` function (lines 1187-1221) to detect runtime injection requirements in tool signatures, similar to `_get_store_arg()`.\n\n4. **Updated ToolNode initialization**: Added `tool_to_runtime_arg` dictionary to track runtime injection requirements for each tool (line 345), and populated it during initialization (line 354).\n\n5. **Implemented _inject_runtime method**: Added `_inject_runtime()` method (lines 668-703) to extract runtime from config and inject it into tool calls.\n\n6. **Updated inject_tool_args method**: Modified `inject_tool_args()` to include runtime injection (lines 704-760), adding a config parameter and calling `_inject_runtime()` after store injection.\n\nThe implementation follows the existing patterns for state and store injection, ensuring consistency and maintainability. Tools can now use `Annotated[Runtime, InjectedRuntime()]` to receive runtime injection." }, { "index": 1, "plan": "**Export InjectedRuntime from prebuilt package**\n- Add `InjectedRuntime` to the imports and exports in `libs/prebuilt/langgraph/prebuilt/__init__.py` (around line 17)\n- Ensure it's included in the `__all__` list for proper public API exposure", "completed": true, "summary": "Successfully exported InjectedRuntime from the prebuilt package:\n\n1. **Added import**: Added `InjectedRuntime` to the imports from `langgraph.prebuilt.tool_node` (line 5)\n\n2. **Added to __all__ list**: Included `InjectedRuntime` in the `__all__` list for proper public API exposure (line 18)\n\nThe changes ensure that `InjectedRuntime` is now publicly accessible when users import from `langgraph.prebuilt`, maintaining consistency with other injection classes like `InjectedState` and `InjectedStore`." }, { "index": 2, "plan": "**Add comprehensive tests for runtime injection**\n- Create test functions in `libs/prebuilt/tests/test_tool_node.py` to verify runtime injection works correctly\n- Test tool with `runtime: Annotated[Runtime, InjectedRuntime]` parameter\n- Test runtime context access within tools\n- Test runtime store access within tools\n- Test error handling when runtime is not available in config\n- Test with both sync and async tools\n- Test that runtime arguments are properly excluded from tool schemas presented to LLMs", "completed": true, "summary": "Successfully added comprehensive tests for runtime injection in `libs/prebuilt/tests/test_tool_node.py`:\n\n1. **test_runtime_injection()**: Tests async tool with runtime injection, verifying runtime is properly injected and can access the store.\n\n2. **test_runtime_injection_sync_tool()**: Tests synchronous tool with runtime injection to ensure both sync and async tools work correctly.\n\n3. **test_runtime_injection_error_no_runtime()**: Tests error handling when runtime is not available in config, ensuring proper error messages are raised.\n\n4. **test_runtime_injection_with_state_and_store()**: Tests that runtime injection works alongside existing state and store injection mechanisms, verifying all three can be used together.\n\n5. **test_runtime_arg_excluded_from_schema()**: Tests that runtime arguments are properly excluded from tool schemas presented to LLMs, ensuring the runtime parameter doesn't appear in the tool's input schema.\n\n6. **test_runtime_injection_with_decorated_tool()**: Tests runtime injection with @tool decorated functions to ensure compatibility with different tool definition styles.\n\nAll tests cover the required scenarios:\n- Runtime parameter injection with `Annotated[Runtime, InjectedRuntime()]`\n- Runtime context and store access within tools\n- Error handling for missing runtime\n- Both sync and async tool support\n- Schema exclusion for LLM presentation\n- Compatibility with existing injection mechanisms" }, { "index": 3, "plan": "**Run formatting, linting, and tests**\n- Navigate to `libs/prebuilt/` directory\n- Run `make format` to format the code\n- Run `make lint` to check for linting issues\n- Run `make test TEST=tests/test_tool_node.py` to run the specific test file and ensure all tests pass", "completed": true, "summary": "Successfully completed formatting, linting, and testing for the runtime injection implementation:\n\n## Formatting (`make format`)\n- Ran successfully, reformatted 5 files total across multiple runs\n- Fixed 1 linting error automatically\n- All code now properly formatted according to project standards\n\n## Linting (`make lint`)\n- All ruff checks passed\n- All files properly formatted (18 files)\n- Import sorting checks passed\n- MyPy type checking successful with no issues in 5 source files\n\n## Testing\n- Fixed critical bug where config wasn't being passed through `_parse_input` to `inject_tool_args`\n- All 6 runtime injection tests passing:\n 1. `test_runtime_injection` - Tests async tool with runtime injection\n 2. `test_runtime_injection_sync_tool` - Tests sync tool with runtime injection \n 3. `test_runtime_injection_error_no_runtime` - Tests error handling\n 4. `test_runtime_injection_with_state_and_store` - Tests combined injections\n 5. `test_runtime_arg_excluded_from_schema` - Tests schema metadata\n 6. `test_runtime_injection_with_decorated_tool` - Tests @tool decorator\n\n## Key Implementation Fixes\n- Added config parameter to `_parse_input` method signature\n- Updated `_parse_input` to pass config to `inject_tool_args`\n- Fixed both sync and async invocation paths to pass config through\n- Corrected test expectations for schema validation\n\nThe runtime injection feature is now fully implemented, tested, and ready for use." } ], "createdAt": 1755864331842, "createdBy": "agent" } ], "activeRevisionIndex": 0, "pullRequestNumber": 5991, "completedAt": 1755865464980, "summary": "I've successfully implemented runtime injection support for LangGraph tools. The implementation allows tools to access runtime context via `Annotated[Runtime, InjectedRuntime()]`, following existing patterns for state and store injection. All tests pass, and the feature is now ready for use in LangGraph workflows. The key improvements include seamless runtime access, compatibility with sync/async tools, and maintaining a clean interface for language models." } ], "activeTaskIndex": 0 }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions