context coercion #867

Closed
opened 2026-02-20 17:42:10 -05:00 by yindo · 1 comment
Owner

Originally created by @sydney-runkle on GitHub (Jul 30, 2025).

Originally assigned to: @sydney-runkle on GitHub.

Privileged issue

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

Issue Content

Currently, the LangGraph APIs for pregel and compiled state graph support a context argument that is typed as context_schema.

context_schema supports typed dicts, dataclasses, and pydantic models. One problem that we have is that we don't currently coerce dict type input to the corresponding dataclasses or pydantic models. We should do this so that API requests can pass a dict type to context and coercion is done under the hood.

Please implement this fix!

Agent Context { "tasks": [ { "id": "92e0d8a5-010c-494c-8f30-632d71f4b845", "taskIndex": 0, "request": "[original issue]\n**context coercion**\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\nCurrently, the LangGraph APIs for pregel and compiled state graph support a `context` argument that is typed as `context_schema`.\n\n`context_schema` supports typed dicts, dataclasses, and pydantic models. One problem that we have is that we don't currently coerce dict type input to the corresponding dataclasses or pydantic models. We should do this so that API requests can pass a dict type to `context` and coercion is done under the hood.\n\nPlease implement this fix!", "title": "Implement context coercion for LangGraph APIs to convert dict inputs to dataclasses/pydantic models", "createdAt": 1753895735102, "completed": true, "planRevisions": [ { "revisionIndex": 0, "plans": [ { "index": 0, "plan": "**Implement context coercion function and apply it in pregel/main.py**\n\nIn `/home/daytona/langgraph/libs/langgraph/langgraph/pregel/main.py`:\n- Add a `_coerce_context` function after the imports section (around line 100) that takes a context_schema and context value\n- The function should check if context is a dict and context_schema is not None\n- Handle three cases: Pydantic BaseModel (use model constructor), dataclass (use constructor), TypedDict (pass through as-is)\n- Apply coercion in three locations before creating Runtime objects:\n - In `stream` method around line 2573-2574\n - In `astream` method around line 2868-2869 \n - The `invoke` method calls `stream`, so it will inherit the fix\n- Import any additional utilities if needed", "completed": true, "summary": "Successfully implemented context coercion for LangGraph APIs in pregel/main.py.\n\n**Changes made:**\n1. Added `_coerce_context` function (lines 147-184) that handles coercion of dict inputs to the appropriate schema type:\n - Handles Pydantic BaseModel by calling the model constructor\n - Handles dataclasses by calling the constructor\n - Handles TypedDict by passing through as-is (since they're dicts at runtime)\n - Includes proper error handling for TypedDict isinstance checks\n\n2. Applied the coercion in both Runtime creation locations:\n - `stream` method (line 2615): Changed `context=context` to `context=_coerce_context(self.context_schema, context)`\n - `astream` method (line 2910): Changed `context=context` to `context=_coerce_context(self.context_schema, context)`\n - The `invoke` method automatically inherits the fix since it calls `stream`\n\n3. All necessary imports were already present in the file (is_dataclass, isclass, BaseModel, is_typeddict).\n\nThe implementation ensures that API users can now pass dicts as context and have them automatically coerced to the expected schema type (dataclass, Pydantic model, or TypedDict)." }, { "index": 1, "plan": "**Add comprehensive tests for context coercion**\n\nIn `/home/daytona/langgraph/libs/langgraph/tests/test_runtime.py`:\n- Add test cases for dict-to-dataclass coercion\n- Add test cases for dict-to-Pydantic model coercion\n- Add test cases for TypedDict context (should pass through)\n- Test edge cases: None context, invalid dict keys, missing required fields\n- Ensure tests cover both sync (`invoke`/`stream`) and async (`astream`) methods", "completed": true, "summary": "Successfully added comprehensive tests for context coercion in `/home/daytona/langgraph/libs/langgraph/tests/test_runtime.py`.\n\n**Tests added:**\n\n1. **`test_context_coercion_dataclass()`** - Verifies dict inputs are coerced to dataclass instances:\n - Tests dict with all fields\n - Tests dict with only required fields (defaults applied)\n - Tests actual dataclass instance still works\n\n2. **`test_context_coercion_pydantic()`** - Verifies dict inputs are coerced to Pydantic models:\n - Tests dict with all fields including lists\n - Tests dict with only required fields (defaults applied)\n - Tests actual Pydantic instance still works\n\n3. **`test_context_coercion_typeddict()`** - Verifies TypedDict context passes through as dict\n\n4. **`test_context_coercion_none()`** - Tests None context handling:\n - Explicit None context\n - Missing context parameter\n\n5. **`test_context_coercion_errors()`** - Tests error cases:\n - Missing required fields raises TypeError\n - Invalid dict keys raise TypeError\n\n6. **`test_context_coercion_async()`** - Tests async methods:\n - `ainvoke` with dict context coercion\n - `astream` with dict context coercion\n\n7. **`test_context_coercion_stream()`** - Tests sync `stream` method with dict context coercion\n\nAll tests cover the required scenarios and edge cases, ensuring the context coercion functionality works correctly across all API methods." }, { "index": 2, "plan": "**Run tests and formatters**\n\nIn the `/home/daytona/langgraph/libs/langgraph/` 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_runtime.py` to run the specific test file\n- Fix any issues that arise from linting or tests", "completed": true, "summary": "Successfully ran all formatters and tests in `/home/daytona/langgraph/libs/langgraph/`.\n\n**Actions taken:**\n\n1. **Ran `make format`**:\n - Executed successfully\n - 2 files were reformatted (the files we modified)\n - All import sorting checks passed\n\n2. **Ran `make lint`**:\n - All ruff checks passed\n - No formatting differences found\n - Import sorting validated\n - MyPy type checking passed with no issues in 64 source files\n\n3. **Ran `make test TEST=tests/test_runtime.py`**:\n - Initially had 1 failure: async test needed proper decorator\n - Fixed by adding `@pytest.mark.anyio` decorator to `test_context_coercion_async`\n - Re-ran tests: All 12 tests passed successfully\n - Test execution time: 0.18s\n\n4. **Cleanup**:\n - Removed temporary files created during implementation\n\nAll code quality checks passed and all tests are working correctly. The context coercion implementation is complete and fully tested." } ], "createdAt": 1753895735102, "createdBy": "agent" } ], "activeRevisionIndex": 0, "pullRequestNumber": 5736, "completedAt": 1753896746375, "summary": "Implemented a `_coerce_context` function in `pregel/main.py` to coerce dict inputs to dataclass, Pydantic model, or pass through TypedDicts; applied it in `stream` and `astream` methods. Added comprehensive tests covering dict coercion, TypedDict pass-through, None context, error cases, and both sync/async methods in `tests/test_runtime.py`. Ran formatters, lint, and tests with all passing after fixing async test decorator. Task complete and fully verified." } ], "activeTaskIndex": 0 }
Originally created by @sydney-runkle on GitHub (Jul 30, 2025). Originally assigned to: @sydney-runkle on GitHub. ### Privileged issue - [x] I am a LangGraph maintainer, or was asked directly by a LangGraph maintainer to create an issue here. ### Issue Content Currently, the LangGraph APIs for pregel and compiled state graph support a `context` argument that is typed as `context_schema`. `context_schema` supports typed dicts, dataclasses, and pydantic models. One problem that we have is that we don't currently coerce dict type input to the corresponding dataclasses or pydantic models. We should do this so that API requests can pass a dict type to `context` and coercion is done under the hood. Please implement this fix! <details> <summary>Agent Context</summary> <open-swe-do-not-edit-task-plan> { "tasks": [ { "id": "92e0d8a5-010c-494c-8f30-632d71f4b845", "taskIndex": 0, "request": "[original issue]\n**context coercion**\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\nCurrently, the LangGraph APIs for pregel and compiled state graph support a `context` argument that is typed as `context_schema`.\n\n`context_schema` supports typed dicts, dataclasses, and pydantic models. One problem that we have is that we don't currently coerce dict type input to the corresponding dataclasses or pydantic models. We should do this so that API requests can pass a dict type to `context` and coercion is done under the hood.\n\nPlease implement this fix!", "title": "Implement context coercion for LangGraph APIs to convert dict inputs to dataclasses/pydantic models", "createdAt": 1753895735102, "completed": true, "planRevisions": [ { "revisionIndex": 0, "plans": [ { "index": 0, "plan": "**Implement context coercion function and apply it in pregel/main.py**\n\nIn `/home/daytona/langgraph/libs/langgraph/langgraph/pregel/main.py`:\n- Add a `_coerce_context` function after the imports section (around line 100) that takes a context_schema and context value\n- The function should check if context is a dict and context_schema is not None\n- Handle three cases: Pydantic BaseModel (use model constructor), dataclass (use constructor), TypedDict (pass through as-is)\n- Apply coercion in three locations before creating Runtime objects:\n - In `stream` method around line 2573-2574\n - In `astream` method around line 2868-2869 \n - The `invoke` method calls `stream`, so it will inherit the fix\n- Import any additional utilities if needed", "completed": true, "summary": "Successfully implemented context coercion for LangGraph APIs in pregel/main.py.\n\n**Changes made:**\n1. Added `_coerce_context` function (lines 147-184) that handles coercion of dict inputs to the appropriate schema type:\n - Handles Pydantic BaseModel by calling the model constructor\n - Handles dataclasses by calling the constructor\n - Handles TypedDict by passing through as-is (since they're dicts at runtime)\n - Includes proper error handling for TypedDict isinstance checks\n\n2. Applied the coercion in both Runtime creation locations:\n - `stream` method (line 2615): Changed `context=context` to `context=_coerce_context(self.context_schema, context)`\n - `astream` method (line 2910): Changed `context=context` to `context=_coerce_context(self.context_schema, context)`\n - The `invoke` method automatically inherits the fix since it calls `stream`\n\n3. All necessary imports were already present in the file (is_dataclass, isclass, BaseModel, is_typeddict).\n\nThe implementation ensures that API users can now pass dicts as context and have them automatically coerced to the expected schema type (dataclass, Pydantic model, or TypedDict)." }, { "index": 1, "plan": "**Add comprehensive tests for context coercion**\n\nIn `/home/daytona/langgraph/libs/langgraph/tests/test_runtime.py`:\n- Add test cases for dict-to-dataclass coercion\n- Add test cases for dict-to-Pydantic model coercion\n- Add test cases for TypedDict context (should pass through)\n- Test edge cases: None context, invalid dict keys, missing required fields\n- Ensure tests cover both sync (`invoke`/`stream`) and async (`astream`) methods", "completed": true, "summary": "Successfully added comprehensive tests for context coercion in `/home/daytona/langgraph/libs/langgraph/tests/test_runtime.py`.\n\n**Tests added:**\n\n1. **`test_context_coercion_dataclass()`** - Verifies dict inputs are coerced to dataclass instances:\n - Tests dict with all fields\n - Tests dict with only required fields (defaults applied)\n - Tests actual dataclass instance still works\n\n2. **`test_context_coercion_pydantic()`** - Verifies dict inputs are coerced to Pydantic models:\n - Tests dict with all fields including lists\n - Tests dict with only required fields (defaults applied)\n - Tests actual Pydantic instance still works\n\n3. **`test_context_coercion_typeddict()`** - Verifies TypedDict context passes through as dict\n\n4. **`test_context_coercion_none()`** - Tests None context handling:\n - Explicit None context\n - Missing context parameter\n\n5. **`test_context_coercion_errors()`** - Tests error cases:\n - Missing required fields raises TypeError\n - Invalid dict keys raise TypeError\n\n6. **`test_context_coercion_async()`** - Tests async methods:\n - `ainvoke` with dict context coercion\n - `astream` with dict context coercion\n\n7. **`test_context_coercion_stream()`** - Tests sync `stream` method with dict context coercion\n\nAll tests cover the required scenarios and edge cases, ensuring the context coercion functionality works correctly across all API methods." }, { "index": 2, "plan": "**Run tests and formatters**\n\nIn the `/home/daytona/langgraph/libs/langgraph/` 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_runtime.py` to run the specific test file\n- Fix any issues that arise from linting or tests", "completed": true, "summary": "Successfully ran all formatters and tests in `/home/daytona/langgraph/libs/langgraph/`.\n\n**Actions taken:**\n\n1. **Ran `make format`**:\n - Executed successfully\n - 2 files were reformatted (the files we modified)\n - All import sorting checks passed\n\n2. **Ran `make lint`**:\n - All ruff checks passed\n - No formatting differences found\n - Import sorting validated\n - MyPy type checking passed with no issues in 64 source files\n\n3. **Ran `make test TEST=tests/test_runtime.py`**:\n - Initially had 1 failure: async test needed proper decorator\n - Fixed by adding `@pytest.mark.anyio` decorator to `test_context_coercion_async`\n - Re-ran tests: All 12 tests passed successfully\n - Test execution time: 0.18s\n\n4. **Cleanup**:\n - Removed temporary files created during implementation\n\nAll code quality checks passed and all tests are working correctly. The context coercion implementation is complete and fully tested." } ], "createdAt": 1753895735102, "createdBy": "agent" } ], "activeRevisionIndex": 0, "pullRequestNumber": 5736, "completedAt": 1753896746375, "summary": "Implemented a `_coerce_context` function in `pregel/main.py` to coerce dict inputs to dataclass, Pydantic model, or pass through TypedDicts; applied it in `stream` and `astream` methods. Added comprehensive tests covering dict coercion, TypedDict pass-through, None context, error cases, and both sync/async methods in `tests/test_runtime.py`. Ran formatters, lint, and tests with all passing after fixing async test decorator. Task complete and fully verified." } ], "activeTaskIndex": 0 } </open-swe-do-not-edit-task-plan> </details>
yindo added the open-swe-max-auto label 2026-02-20 17:42:10 -05:00
yindo closed this issue 2026-02-20 17:42:10 -05:00
Author
Owner

@open-swe[bot] commented on GitHub (Jul 30, 2025):

🤖 Open SWE has been triggered for this issue. Processing...

View run in Open SWE here (this URL will only work for @sydney-runkle)

Dev Metadata { "runId": "1f06d681-c342-661f-99c3-4f049bb41608", "threadId": "0d4f04b9-c0e3-47a1-a7cc-2e5e11fb53fa" }

🤖 Plan Generated

I've generated a plan for this issue and will proceed to implement it since auto-accept is enabled.

Plan: Implement context coercion for LangGraph APIs to convert dict inputs to dataclasses/pydantic models

  • Task 1:
**Implement context coercion function and apply it in pregel/main.py**

In `/home/daytona/langgraph/libs/langgraph/langgraph/pregel/main.py`:
- Add a `_coerce_context` function after the imports section (around line 100) that takes a context_schema and context value
- The function should check if context is a dict and context_schema is not None
- Handle three cases: Pydantic BaseModel (use model constructor), dataclass (use constructor), TypedDict (pass through as-is)
- Apply coercion in three locations before creating Runtime objects:
  - In `stream` method around line 2573-2574
  - In `astream` method around line 2868-2869  
  - The `invoke` method calls `stream`, so it will inherit the fix
- Import any additional utilities if needed
  • Task 2:
**Add comprehensive tests for context coercion**

In `/home/daytona/langgraph/libs/langgraph/tests/test_runtime.py`:
- Add test cases for dict-to-dataclass coercion
- Add test cases for dict-to-Pydantic model coercion
- Add test cases for TypedDict context (should pass through)
- Test edge cases: None context, invalid dict keys, missing required fields
- Ensure tests cover both sync (`invoke`/`stream`) and async (`astream`) methods
  • Task 3:
**Run tests and formatters**

In the `/home/daytona/langgraph/libs/langgraph/` directory:
- Run `make format` to format the code
- Run `make lint` to check for linting issues
- Run `make test TEST=tests/test_runtime.py` to run the specific test file
- Fix any issues that arise from linting or tests

Proceeding to implementation...

@open-swe[bot] commented on GitHub (Jul 30, 2025): 🤖 Open SWE has been triggered for this issue. Processing... View run in Open SWE [here](https://swe.langchain.com/chat/0d4f04b9-c0e3-47a1-a7cc-2e5e11fb53fa) (this URL will only work for @sydney-runkle) <details> <summary>Dev Metadata</summary> { "runId": "1f06d681-c342-661f-99c3-4f049bb41608", "threadId": "0d4f04b9-c0e3-47a1-a7cc-2e5e11fb53fa" } </details> <open-swe-plan-message> ### 🤖 Plan Generated I've generated a plan for this issue and will proceed to implement it since auto-accept is enabled. **Plan: Implement context coercion for LangGraph APIs to convert dict inputs to dataclasses/pydantic models** - Task 1: ``` **Implement context coercion function and apply it in pregel/main.py** In `/home/daytona/langgraph/libs/langgraph/langgraph/pregel/main.py`: - Add a `_coerce_context` function after the imports section (around line 100) that takes a context_schema and context value - The function should check if context is a dict and context_schema is not None - Handle three cases: Pydantic BaseModel (use model constructor), dataclass (use constructor), TypedDict (pass through as-is) - Apply coercion in three locations before creating Runtime objects: - In `stream` method around line 2573-2574 - In `astream` method around line 2868-2869 - The `invoke` method calls `stream`, so it will inherit the fix - Import any additional utilities if needed ``` - Task 2: ``` **Add comprehensive tests for context coercion** In `/home/daytona/langgraph/libs/langgraph/tests/test_runtime.py`: - Add test cases for dict-to-dataclass coercion - Add test cases for dict-to-Pydantic model coercion - Add test cases for TypedDict context (should pass through) - Test edge cases: None context, invalid dict keys, missing required fields - Ensure tests cover both sync (`invoke`/`stream`) and async (`astream`) methods ``` - Task 3: ``` **Run tests and formatters** In the `/home/daytona/langgraph/libs/langgraph/` directory: - Run `make format` to format the code - Run `make lint` to check for linting issues - Run `make test TEST=tests/test_runtime.py` to run the specific test file - Fix any issues that arise from linting or tests ``` Proceeding to implementation... </open-swe-plan-message>
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraph#867