mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-07-15 12:35:43 -04:00
Refactor create_react_agent to Enforce Structured Output in Agent Node #915
Closed
opened 2026-02-20 17:42:21 -05:00 by yindo
·
5 comments
No Branch/Tag Specified
main
jdr/add-session-name
deps/uv-lock-upgrade
fix/root-messages-inbox-bound
open-swe/fix-thread-actions-auth
fix/sdk-integration-ci-secrets
corridor/fix-e588a881-1783566949463
long/update-state-delta-fix-2
long/delta-replay-fix
open-swe/convert-to-ty
hunter/persist-interrupt-writes
longquanzheng-patch-1
test-json-overwrite-sentinel
fix-delta-overwrite-binop-semantics
sydney-runkle/langgraph/delta-channel-checkpointer-warning
open-swe/langsmith-multi-project-replicas
sydney/langgraph/overwrite-json-erasure
release/cli-0.4.28
mdrxy/store-docstring-pass
chore/adopt-mypy-2.1.0
cb/fix-set-node-defaults-cache-policy-opt-out
cb/fix-delta-channel-migration-writes
nh/sdk-py-sync-subgraph-stream-fix
cb/fix-delta-channel-overwrite-replay-divergence
jdr/uv-check
nh/sdk-py-v3-streaming-overview-rfc
worktree-refactor-error-handler-as-policy
parker/time-travel
feat/hook-chaining
nh/namespace-keyed-subagents
long/delta-prune-comment
long/delta-exit-mode
sr/messages-delta-reducer-uuid-assignment
open-swe/c802e0ea-c9e5-c8c6-824a-c065dd2bfd6f
long/delta-chan-combine
sr/delta-channel-no-streaming
nh/streaming-for-alpha-release
v1.0.13
delta-channel-writes-based
nh/langgraph-api-test-branch
cb/remote-graph-update
sr/snapshot-freq-bench
delta-channel-writes-based-qlong-test-sends
release/langgraph-1.1.10
cb/new-streaming
nh/subgraph-lifecycle
sr/even-better-writes-idea
sr/deepagents-perf-delta-plus-addmsgs
sr/deepagents-perf-combo
optimize/add-messages-fast-path
perf/get-function-nonlocals
diff-channel-incremental-checkpointing
wfh/diff_channel_opt_2
sr/deferred-imports
nh/tools-channel-streaming
jacob/metadatamerging
nh/streaming-with-event-log
open-swe/873b84e2-cbfb-bfdd-5e41-5f638d107a55
nh/streaming-v2
wfh/bp
open-swe/a2e2088a-1fd1-eb4d-a880-5469f1ebb7b5
wfh/conformance_format
wfh/gocli
wfh/cli_validate
wfh/releases/cli
cc/stream_mode_events
cb/lg-readme-update
hunter/interrupt-callback-lg
wfh/rename-langgraph-json-to-langsmith-json
fix/deploy-name-underscore-validation
sr/another-time-travel-fix
cb/multiple-http-app-support-a79b
wfh/build_fail_check
long/advanced-graph-rust-core-published
wfh/swr_cache
cb/protocol-improvements
wfh/releases/langgraph/1.1.4
long/advanced-graph-rust-core-published-po3
long/advanced-graph-rust-core-published-libc
long/advanced-graph-rust-core
wfh/releases/checkpoitners/4.0.2
long/advanced-graph
open-swe/feb956aa-a579-4d04-6b03-2bd214f26c7a
sr/remote-graph-generics
jk/optimizations
jk/optimizations-rebased
jk/cache-optimizations
david/lg-deploy-remote-build
long/dr-0309-version
update-llmstxt
an/09mar/cli-list-deployments
an/09mar/lg-list-deployments
sr/rippling-asks
worktree-explore-subgraph-replay
sr/third-attempt
sr/alt-fix
sr/potential_fix
sr/new-time-travel-tests
sr/1.1-v2-default
sr/logos
mdrxy/cross-process-test
sr/simplify-invoke-interrupts
wfh/cli/bazelbaby
wfh/agent-server-config
sr/streaming-hints
wfh/postgres-extended-methods
wfh/build-checkpointer-skill
wfh/respect_defaults
jk/js-yaml
wfh/testpypi_pyproject
wfh/_/native_cli
david/cache-optimized-dockerfile-v2
jdr/add-append-only-mode
claude/durable-retry-policy-hohXq
fix/add-assistant-id-to-auth-types
sr/tool-node-dynamic
wfh/topology
wfh/fix_hasalive
wfh/allowlist
caspar/msgpack_allowlist
wfh/honor_traceable
wfh/prune
mdrxy/pyodide-wasm-support
wfh/astream_events
wfh/verify
wfh/remote_graph_wait
wfh/listen
long/versions-seen-learning
wfh/flip_default_base_cache
eugene/patch
sr/response-schema-mwahaha
wfh/release_sdk
wfh/increase_default
wfh/fix_ci
wfh/sdk_py/release
update-openapi-spec-v0.5.26
update-openapi-spec-v0.5.25
update-openapi-spec-v0.5.24
update-openapi-spec-v0.5.23
update-openapi-spec-v0.5.20
sr/tool-request
update-openapi-spec-v0.5.17
update-openapi-spec-v0.5.16
update-openapi-spec-v0.5.14
sr/dep-warning-fixes
sr/linting-fixes
mdrxy/add-return-types
issue_6409
sr/new-fix
wfh/cli_int_update
wfh/trigger_changelog
copilot/sub-pr-6316
0.6
caspar/interrupt_scheduling_optimization_fix
david/10-07/cache-optimized-dockerfile
update-openapi-spec-v0.4.39
harrison/overwrite
mdrxy/lift-core-dep
caspar/fix_subgraph_state_replay
mdrxy/lc-ref-consolidate
randall-aaa899d9-8505-4622-9aa0-5cb797c2db63
joaquin/test-push-protection-datadog-revoked-key
open-swe/01d3b562-feb8-4631-b7de-fc3d9970c700
wfh/omit_more2
caspar/functional-api-mypy-typing
long-test-push
sr/what-if-we-did-typed-dict
sr/model-request-as-node
nc/25aug/agent
wfh/update_type
sr/fix-tool-node
update-openapi-spec-v0.4.4
update-openapi-spec-v0.4.3
update-openapi-spec-v0.4.2
eugene/update_agent_implementation
update-openapi-spec-v0.3.4
open-swe/89802a32-3c61-420c-990b-e6bcebee5459
open-swe/239867ad-46ba-4f8c-ba65-0483e8bf54ac
sr/drop-3.9
david/08-21/update-nat-ips
wfh/0.6.6
update-openapi-spec-v0.2.135
eugene/inject_runtime_in_tools
eugene/add_structured_response
sr/structured-outputs-draft
open-swe/c85f411c-dfc5-4894-ab9a-124661d9ab43
open-swe/bc2ef87c-6f38-432d-b4c3-ac46c27feb34
wfh/accept_extra_args
wfh/bump_cli
sr/new-msg-support
eugene/test_multiple_interrupt_with_send
open-swe/13bd038a-d872-4620-8474-04453d65376e
open-swe/6567da56-b47e-4b9c-b9c8-0c15eb3573a6
eugene/allow_default_name
open-swe/ae08c4ba-71fe-4b12-bd45-dd7cdf82ebe8
changelog-bot-update-d303e041
sr/fix-dep-warning
open-swe/e61ca3a1-8559-4dcc-a859-476b55a12775
open-swe/1d37d949-de60-4999-85ec-b835dd3fa7f8
eugene/document_dynamic_models
remove-lgp-content-mkdocs
sr/fix-context-coercion
hunter/js-preview
open-swe/d532baf6-ca9e-4246-b3f0-3ca77d4ce3c8
sr/experimental-refactor
open-swe/e5610d6c-992d-4e1f-89c1-452f9f0cfd37
open-swe/97c901db-9ad0-4dc8-bad3-d64bed36d9b2
eugene/script_to_replace_cross_refs
copilot/fix-5692
eugene/getting-started
eugene/update_cross_refs
docs/js
open-swe/f801d704-025e-4441-950c-12ffb2484849
eugene/refactor_create_react_agent
sr/fixes-for-v6
open-swe/2f1220bd-1fac-476d-8346-9cd31ef4baeb
open-swe/773f034b-9148-4456-9365-059d120fc606
open-swe/654a2f9f-75b5-472d-8991-b817dd33f0a1
open-swe/a84821fc-711e-456f-baa1-5ee6451d91b2
hunter/translation-docs-review
eugene/add_dynamic_model
open-swe/27f6f9f5-5fcf-4761-b6b6-3e4e18b5ce17
open-swe/d0aec071-9bbd-41f2-9a9c-ae02e5cdd4e5
eugene/docs_customer_custom_workflow
dqbd/translation-ref
changelog-bot-update-5265f6ce
infra/remove-api-key-v0
infra/remove-license-key-v0
changelog-bot-update-01d2ca7b
sam_testing_bot_from_version_85
open-swe/f9241737-35f7-450d-8486-d3b69266be57
changelog-bot-update-19ff701b
changelog-bot-update-8fd71780
changelog-bot-update-fc671586
changelog-bot-update-96f0bf39
changelog-bot-update-6140158c
changelog-bot-update-0c2eec86
add-copy-page-button
sr/fix-3.11
wfh/update_doc
sr/min-deps-simplified
sr/min-deps-testing
sr/perms-for-pr
sr/remove-message-graph
eugene/nav_reshuffle_2
eugene/navigation_links
eugene/add_more_cross_links
0.4
eugene/tools
sr/invokable-state-node
arjun/docs_data_storage
arjun/docs_studio_evals
eugene/conditional-rendering-global
eugene/conditional-rendering
wfh/tavilyp2
open-swe/3817d5e5-d827-4dd8-9622-db5b5da74e0d
rlm/local-testing
wfh/golang
sr/run-against-checkpoint-min
arjun/consolidate_installation
sr/update-pydantic-in-lockfile
wfh/inlineforpeoplewhocantread
wfh/header_handling2
wfh/header_handling
wfh/anymessage
wfh/add_test_generics
wfh/validate_again
wfh/_/validate_native_time
wfh/mount_prefix_sdk
wfh/pg_example
wfh/memcheck
wfh/readme_nits
wfh/set_store
wfh/cli_from_module
wfh/cli_release_studio
wfh/gc_test_all
wfh/automaton
brian/typo
nc/1mar/java
nc/1mar/lite
dqbd/sdk-js-0.0.46
wfh/cli/http_with_faux
wfh/sdk/router
ben/ts-exec
rlm/agent_fxn_api
wfh/update_dev_msg
wfh/queue_metrics
wfh/release
wfh/_/illbeback
wfh/clarify_installation
wfh/scaling
wfh/simple_scaling
wfh/docs/memstoreconcept
wfh/_/ann
wfh/_/annp0
wfh/store/avs
wfh/store/avs_backup
wfh/config/store_config
wfh/_/pgsearch
wfh/winpaths
wfh/cli/inmem_update
erick/langgraph-get-rid-of-beta-uvloop-version
wfh/inmemory
wfh/update-stae-modifier
rlm/chat-langgraph
wfh/stateinjection
jacoblee93-patch-1
cli==0.4.31
1.2.9
1.2.8
1.2.7
1.2.6
cli==0.4.30
1.2.5
cli==0.4.29
cli==0.4.28
1.2.4
1.2.3
sdk==0.4.2
sdk==0.4.1
cli==0.4.27
sdk==0.4.0
1.2.2
checkpoint==4.1.1
sdk==0.3.15
1.2.1
prebuilt==1.1.0
checkpointpostgres==3.1.0
checkpoint==4.1.0
1.2.0
checkpointsqlite==3.1.0
cli==0.4.26
cli==0.4.25
checkpointsqlite==3.1.0a1
sdk==0.3.14
1.2.0a7
checkpointpostgres==3.1.0a4
checkpoint==4.1.0a4
1.2.0a6
1.2.0a5
prebuilt==1.1.0a2
prebuilt==1.1.0a1
1.2.0a4
1.2.0a3
checkpointpostgres==3.1.0a3
checkpoint==4.1.0a3
checkpoint==4.1.0a2
1.2.0a2
checkpointpostgres==3.1.0a1
prebuilt==1.0.13
1.2.0a1
checkpoint==4.1.0a1
1.1.10
prebuilt==1.0.12
checkpoint==4.0.3
prebuilt==1.0.11
cli==0.4.24
1.1.9
1.1.8
prebuilt==1.0.10
cli==0.4.23
1.1.7
cli==0.4.22
checkpoint==4.0.2
1.1.7a2
1.1.7a1
cli==0.4.21
cli==0.4.20
sdk==0.3.13
1.1.6
prebuilt==1.0.9
1.1.5
1.1.4
cli==0.4.19
1.1.3
sdk==0.3.12
checkpointpostgres==3.0.5
cli==0.4.18
cli==0.4.17
cli==0.4.16
1.1.2
1.1.1
sdk==0.3.11
1.1.0
cli==0.4.15
sdk==0.3.10
cli==0.4.14
1.0.10
checkpoint==4.0.1
checkpoint==4.0.1rc3
checkpoint==4.0.1rc2
1.0.10rc1
checkpoint==4.0.1rc1
sdk==0.3.9
sdk==0.3.8
prebuilt==1.0.8
1.0.9
sdk==0.3.7
sdk==0.3.6
sdk==0.3.5
1.0.8
sdk==0.3.4
checkpointpostgres==3.0.4
cli==0.4.12
prebuilt==1.0.7
1.0.7
checkpointsqlite==3.0.3
sdk==0.3.3
checkpoint==4.0.0
1.0.6
checkpointpostgres==3.0.3
checkpointsqlite==3.0.2
prebuilt==1.0.6
sdk==0.3.2
sdk==0.3.1
cli==0.4.11
cli==0.4.10
1.0.5
sdk==0.3.0
checkpointpostgres==3.0.2
checkpointsqlite==3.0.1
sdk==0.2.15
cli==0.4.9
cli==0.4.8
sdk==0.2.14
sdk==0.2.12
1.0.4
sdk==0.2.10
prebuilt==1.0.5
prebuilt==1.0.4
prebuilt==1.0.3
1.0.3
checkpointpostgres==3.0.1
checkpoint==3.0.1
cli==0.4.7
cli==0.4.6
cli==0.4.5
1.0.2
prebuilt==1.0.2
prebuilt==0.6.5
0.6.11
checkpointpostgres==3.0.0
prebuilt==1.0.1
checkpointsqlite==3.0.0
1.0.1
checkpoint==3.0.0
1.0.0
prebuilt==1.0.0
prebuilt==0.7.0rc1
cli==0.4.4
1.0.0rc1
0.6.10
cli==0.4.3
0.6.9
checkpointpostgres==2.0.25
checkpoint==2.1.2
checkpointpostgres==2.0.24
1.0.0a4
0.6.8
sdk==0.2.9
sdk==0.2.8
sdk==0.2.7
1.0.0a3
0.6.7
cli==0.4.2
cli==0.4.1
sdk==0.2.6
sdk==0.2.5
1.0.0a2
prebuilt==0.7.0a2
sdk==0.2.4
1.0.0a1
prebuilt==0.7.0a1
cli==0.4.0
sdk==0.2.3
cli==0.3.8
cli==0.3.7
0.6.6
sdk==0.2.2
sdk==0.2.1
0.6.5
prebuilt==0.6.4
0.6.4
0.6.3
prebuilt==0.6.3
0.6.2
prebuilt==0.6.2
0.6.1
prebuilt==0.6.1
0.6.0
prebuilt==0.6.0
0.6.0a2
prebuilt==0.6.0a1
checkpointsqlite==2.0.11
cli==0.3.6
sdk==0.2.0
sdk==0.2.0a1
0.6.0a1
0.5.4
sdk==0.1.74
cli==0.3.5
checkpoint==2.1.1
checkpointpostgres==2.0.23
sdk==0.1.73
0.5.3
checkpointpostgres==2.0.22
0.5.2
cli==0.3.4
0.5.1
prebuilt==0.5.2
prebuilt==0.5.1
sdk==0.1.72
0.5.0
prebuilt==0.5.0
sdk==0.1.71
prebuilt==0.2.3
0.4.10
0.4.9
0.5.0rc1
prebuilt==0.5.0rc0
0.5.0rc0
checkpoint==2.1.0
cli==0.3.3
cli==0.3.2
cli==0.3.1
cli==0.2.12
cli==0.2.11
0.4.8
prebuilt==0.2.2
0.4.7
0.4.6
prebuilt==0.2.1
prebuilt==0.2.0
sdk==0.1.70
checkpointsqlite==2.0.10
checkpointsqlite==2.0.9
checkpointsqlite==2.0.8
0.4.5
checkpoint==2.0.26
0.4.4
sdk==0.1.69
cli==0.2.10
cli==0.2.9
0.4.3
0.4.2
checkpointsqlite==2.0.7
cli==0.2.8
sdk==0.1.66
sdk==0.1.65
0.4.1
sdk==0.1.64
0.4.0
checkpoint==2.0.25
0.3.34
0.3.32
cli==0.2.7
cli==0.2.6
sdk==0.1.63
sdk==0.1.62
checkpointpostgres==2.0.21
checkpointpostgres==2.0.20
cli==0.2.5
0.3.31
cli==0.2.4
0.3.30
0.3.29
cli==0.2.3
0.3.28
cli==0.2.2
cli==0.2.1
0.3.27
0.3.26
cli==0.1.89
0.3.25
prebuilt==0.1.8
cli==0.1.84
sdk==0.1.61
0.3.24
checkpoint==2.0.24
0.3.23
cli==0.1.83
0.3.22
cli==0.1.82
cli==0.1.81
sdk==0.1.60
0.3.21
prebuilt==0.1.7
cli==0.1.80
sdk==0.1.59
prebuilt==0.1.6
prebuilt==0.1.5
0.3.20
checkpoint==2.0.23
checkpoint==2.0.22
0.3.19
cli==0.1.79
prebuilt==0.1.4
cli==0.1.78
checkpointpostgres==2.0.19
0.3.18
sdk==0.1.58
0.3.17
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
checkpoint==2.0.21
checkpointpostgres==2.0.18
0.3.11
checkpointpostgres==2.0.17
cli==0.1.77
checkpoint==2.0.20
0.3.10
sdk==0.1.57
prebuilt==0.1.3
0.3.8
cli==0.1.76
sdk==0.1.56
checkpoint==2.0.19
0.3.7
0.3.6
checkpointsqlite==2.0.6
checkpointpostgres==2.0.16
checkpoint==2.0.18
sdk==0.1.55
checkpoint==2.0.17
cli==0.1.75
prebuilt==0.1.2
0.3.5
0.3.4
0.3.3
0.3.2
cli==0.1.74
0.3.1
prebuilt==0.1.1
prebuilt==0.1.0
0.3.0
0.2.76
0.2.75
cli==0.1.73
sdk==0.1.53
cli==0.1.72
0.2.74
checkpoint==2.0.16
0.2.73
checkpointsqlite==2.0.5
checkpointpostgres==2.0.15
checkpoint==2.0.15
checkpoint==2.0.14
0.2.72
checkpoint==2.0.13
checkpointpostgres==2.0.14
checkpointsqlite==2.0.4
0.2.71
checkpoint==2.0.12
cli==0.1.71
0.2.70
0.2.69
cli==0.1.70
0.2.68
cli==0.1.69
0.2.67
0.2.66
0.2.65
cli==0.1.68
0.2.64
0.2.63
checkpointpostgres==2.0.13
checkpointpostgres==2.0.12
checkpointsqlite==2.0.3
checkpoint==2.0.10
checkpointduckdb==2.0.2
checkpointpostgres==2.0.11
checkpointsqlite==2.0.2
cli==0.1.67
cli==0.1.66
0.2.62
checkpointpostgres==2.0.10
sdk==0.1.51
sdk==0.1.50
0.2.61
checkpointpostgres==2.0.9
cli==0.1.65
sdk==0.1.48
0.2.60
sdk==0.1.47
cli==0.1.64
sdk==0.1.46
cli==0.1.63
cli==0.1.62
sdk==0.1.45
checkpoint==2.0.9
sdk==0.1.44
0.2.59
0.2.58
0.2.57
checkpointpostgres==2.0.8
sdk==0.1.43
0.2.56
0.2.55
0.2.54
sdk==0.1.42
checkpoint==2.0.8
checkpointpostgres==2.0.7
checkpointpostgres==2.0.6
cli==0.1.61
cli==0.1.60
checkpointpostgres==2.0.5
sdk==0.1.40
checkpoint==2.0.7
sdk==0.1.39
sdk==0.1.38
sdk==0.1.37
checkpointpostgres==2.0.4
checkpoint==2.0.6
cli==0.1.59
cli==0.1.58
cli==0.1.57
cli==0.1.56
0.2.53
cli==0.1.55
cli==0.1.55rc1
0.2.52
0.2.51
checkpointpostgres==2.0.3
checkpoint==2.0.5
0.2.50
0.2.49
cli==0.1.54
0.2.48
checkpoint==2.0.4
sdk==0.1.36
0.2.47
checkpoint==2.0.3
0.2.46
0.2.45
cli==0.1.53
0.2.44
0.2.43
0.2.42
0.2.41
0.2.40
sdk==0.1.35
sdk==0.1.34
checkpointsqlite==2.0.1
checkpointpostgres==2.0.2
checkpointduckdb==2.0.1
checkpoint==2.0.2
checkpointduckdb==2.0.0
0.2.39
0.2.38
0.2.37
0.2.36
sdk==0.1.33
0.2.35
checkpointpostgres==2.0.1
checkpoint==2.0.1
0.2.34
0.2.33
checkpointpostgres==2.0.0
0.2.32
checkpointsqlite==2.0.0
checkpoint==2.0.0
sdk==0.1.32
checkpointpostgres==1.0.11
0.2.31
checkpointpostgres==1.0.10
0.2.30
checkpoint==1.0.14
0.2.29
checkpoint==1.0.13
checkpointpostgres==1.0.9
checkpoint==1.0.12
0.2.28
0.2.27
0.2.26
checkpointsqlite==1.0.4
checkpointpostgres==1.0.8
checkpoint==1.0.11
0.2.25
sdk==0.1.31
0.2.24
0.2.23
checkpointpostgres==1.0.7
checkpoint==1.0.10
0.2.22
0.2.21
0.2.20
0.2.19
0.2.18
checkpoint==1.0.9
0.2.17
checkpointsqlite==1.0.3
checkpointsqlite==1.0.2
checkpointpostgres==1.0.6
0.2.16
checkpoint==1.0.8
0.2.15
checkpointsqlite==1.0.1
checkpoint==1.0.7
checkpointpostgres==1.0.5
sdk==0.1.30
cli==0.1.52
checkpointpostgres==1.0.4
sdk==0.1.29
0.2.13
cli==0.1.51
0.2.12
checkpoint==1.0.4
0.2.11
0.2.10
0.2.9
sdk==0.1.28
0.2.7
0.2.6
0.2.5
0.2.4
checkpoint==1.0.3
checkpointpostgres==1.0.3
checkpointpostgres==1.0.2
0.2.3
checkpointpostgres==1.0.1
0.2.2
0.2.1
checkpoint==1.0.2
0.2.0
checkpointpostgres==1.0.0
checkpointsqlite==1.0.0
checkpoint==1.0.1
sdk==0.1.27
checkpoint==1.0.0
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
cli==0.1.50
0.1.9
cli==0.1.49
sdk==0.1.26
0.1.8
0.1.7
0.1.6
cli==0.1.48
0.1.5
cli==0.1.47
0.1.4
0.1.3
cli==0.1.46
cli==0.1.45
cli==0.1.45a1
0.1.2
sdk==0.1.25
sdk==0.1.24
cli==0.1.45a0
cli==0.1.44
cli==0.1.42
cli==0.1.41
cli==0.1.40
sdk==0.1.23
langgraph-cli==0.1.39
v0.0.8
v0.0.7
v0.0.6
v0.0.5
v0.0.4
v0.0.3
Labels
Clear labels
agents
awaiting author revision
bug
change
chat models
checkpointer
ci
code quality
code quality
dependencies
documentation
drawing
duplicate
enhancement
good first issue
help wanted
invalid
maintainer
meta
missing information
not maintained by langchain
open-swe-auto
open-swe-max
open-swe-max-auto
pending
performance
pull-request
question
requires design
sdk
server
stale
studio
tests
type checking
usage question
v0.5
v1.1
Mirrored from GitHub Pull Request
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: langchain-ai/langgraph#915
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @sydney-runkle on GitHub (Aug 11, 2025).
I want to refactor the create_react_agent pattern to handle structured output in a different way. I'd like it to enforce structured output in the agent node instead of in a different node.
It should enforce structured output by adding the response_format schema as a tool. When that tool is called, we coerce the args into the response schema, then add an artificial tool message and AI message indicating we've reached a final result.
Agent Context
{ "tasks": [ { "id": "8f7baf4d-26df-417a-a24f-8ab3c4b8c605", "taskIndex": 0, "request": "[original issue]\n**Refactor create_react_agent to Enforce Structured Output in Agent Node**\nI want to refactor the create_react_agent pattern to handle structured output in a different way. I'd like it to enforce structured output in the agent node instead of in a different node.\n\nIt should enforce structured output by adding the response_format schema as a tool. When that tool is called, we coerce the args into the response schema, then add an artificial tool message and AI message indicating we've reached a final result.", "title": "Refactor create_react_agent to enforce structured output in agent node using response schema as tool", "createdAt": 1754942434814, "completed": true, "planRevisions": [ { "revisionIndex": 0, "plans": [ { "index": 0, "plan": "**Modify the `create_react_agent` function in `libs/prebuilt/langgraph/prebuilt/chat_agent_executor.py`** to create a tool from the `response_format` schema when provided. Around lines 500-540, add logic to convert the response_format schema (BaseModel or dict) into a tool that can be bound to the model alongside regular tools. This will involve checking if response_format is provided and creating a tool representation of the schema.", "completed": true, "summary": "**Task 0 Completed: Modified create_react_agent to create tool from response_format schema**\n\nSuccessfully implemented logic in the `create_react_agent` function around lines 502-527 to create a tool from the `response_format` schema when provided. The implementation includes:\n\n1. **Schema extraction**: Added logic to handle both tuple format `(prompt, schema)` and direct schema format\n2. **Tool name generation**: Implemented logic to extract tool names from schema `__name__` attribute, dict `title` field, or default to \"ResponseSchema\"\n3. **Tool integration**: Added the response schema to the `tool_classes` list so it gets bound to the model alongside regular tools\n\nThe key changes made:\n- Added a `response_tool_name` variable to track the response schema tool name\n- Implemented conditional logic to check if `response_format` is provided\n- Added schema extraction logic to handle tuple format `(prompt, schema)`\n- Added tool name resolution logic with fallback options\n- Appended the actual schema to `tool_classes` list for model binding\n\nThis ensures that when `response_format` is provided, the schema is converted into a tool that can be called by the model, setting up the foundation for the new structured output approach that eliminates the need for a separate `generate_structured_response` node." }, { "index": 1, "plan": "**Update the tool binding logic in `create_react_agent`** to include the response schema as a tool when binding tools to the model. Modify the section around lines 530-536 where `model.bind_tools()` is called to include the response schema tool in the tools list, ensuring the model can call both regular tools and the response schema tool.", "completed": true, "summary": "**Task 1 Completed: Updated tool binding logic to include response schema tool**\n\nSuccessfully updated the tool binding logic in `create_react_agent` to ensure the response schema tool is properly bound to the model alongside regular tools. The implementation includes:\n\n1. **Static model binding**: The response schema tool is already included since it was added to the `tool_classes` list in task 0, so the existing `model.bind_tools(tool_classes + llm_builtin_tools)` call automatically includes it.\n\n2. **Dynamic model binding**: Updated both sync and async dynamic model resolution functions (`_resolve_model` and `_aresolve_model`) to properly bind tools including the response schema tool when resolving dynamic models at runtime.\n\nKey changes made:\n- Updated `_resolve_model()` function to bind tools to dynamically resolved models\n- Updated `_aresolve_model()` function to bind tools to both async and sync dynamically resolved models\n- Ensured consistent tool binding logic across static and dynamic model scenarios\n- Maintained the same tool binding conditions using `_should_bind_tools()` helper function\n\nThis ensures that whether using static or dynamic models, the response schema tool is always properly bound to the model, enabling the model to call both regular tools and the response schema tool for structured output generation." }, { "index": 2, "plan": "**Create a new `respond` node function** that handles structured response creation when the response schema tool is called. This function should extract the tool call arguments from the last AI message, coerce them into the response schema using `ResponseSchema(**tool_call['args'])`, create an artificial tool message with content 'Here is your structured response', and return both the structured_response and the tool message.", "completed": true, "summary": "**Task 2 Completed: Created new respond node function**\n\nSuccessfully created both sync and async versions of the `respond` node function that handles structured response creation when the response schema tool is called. The implementation includes:\n\n1. **Sync respond function**: `respond(state, runtime, config)` that:\n - Extracts the last AI message and validates it has tool calls\n - Finds the response schema tool call by matching the `response_tool_name`\n - Handles both tuple format `(prompt, schema)` and direct schema format\n - Coerces tool call arguments into the response schema using `actual_schema(**tool_call[\"args\"])`\n - Creates an artificial `ToolMessage` with content \"Here is your structured response\"\n - Returns both the tool message and structured_response\n\n2. **Async respond function**: `arespond(state, runtime, config)` with identical logic for async workflows\n\nKey features implemented:\n- **Tool call extraction**: Searches through tool calls to find the response schema tool\n- **Schema coercion**: Handles both BaseModel classes and dict schemas\n- **Error handling**: Provides clear error messages for validation failures\n- **Tool message creation**: Creates proper ToolMessage with correct tool_call_id\n- **State updates**: Returns both messages and structured_response in state format\n\nThe functions are positioned after the existing `generate_structured_response` functions and follow the same pattern for consistency with the existing codebase." }, { "index": 3, "plan": "**Modify the `should_continue` routing function** around line 779 to detect when the response schema tool is called and route to the new 'respond' node instead of 'generate_structured_response'. Add logic to check if the last message contains a tool call with the response schema tool name and return 'respond' in that case.", "completed": true, "summary": "**Task 3 Completed: Modified should_continue routing function**\n\nSuccessfully updated the `should_continue` routing function to detect when the response schema tool is called and route to the new 'respond' node instead of 'generate_structured_response'. The implementation includes:\n\n1. **Response schema tool detection**: Added logic to check if `response_format` is provided and `response_tool_name` is not None\n2. **Tool call inspection**: Iterates through tool calls in the last AI message to find calls matching the response schema tool name\n3. **Routing logic**: Returns 'respond' when the response schema tool is detected, ensuring the workflow routes to the new respond node\n4. **Fallback behavior**: Maintains existing routing logic for regular tools and other scenarios\n\nKey changes made:\n- Added conditional check for `response_format is not None and response_tool_name is not None`\n- Added loop to inspect `last_message.tool_calls` for response schema tool name matches\n- Added early return of 'respond' when response schema tool is detected\n- Preserved existing routing logic for v1/v2 versions and regular tool calls\n\nThis ensures that when the model calls the response schema tool, the workflow will route to the new 'respond' node instead of continuing with regular tool execution or the old generate_structured_response approach." }, { "index": 4, "plan": "**Update the workflow construction logic** to add the new 'respond' node instead of the 'generate_structured_response' node when response_format is provided. Replace the sections around lines 757-767 and 842-850 that add the generate_structured_response node with logic to add the respond node and appropriate edges.", "completed": true, "summary": "**Task 4 Completed: Updated workflow construction logic to use respond node**\n\nSuccessfully updated the workflow construction logic to add the new 'respond' node instead of the 'generate_structured_response' node when response_format is provided. The implementation includes:\n\n1. **First workflow section (lines 892-903)**: Replaced `generate_structured_response` node with `respond` node using `RunnableCallable(respond, arespond)`\n\n2. **Second workflow section (lines 983-994)**: Replaced `generate_structured_response` node with `respond` node using `RunnableCallable(respond, arespond)`\n\n3. **Routing logic updates**: Updated all routing references from `\"generate_structured_response\"` to `\"respond\"` in:\n - `should_continue` function routing logic (line 919)\n - `post_model_hook_router` function routing logic (line 1024)\n - Documentation comments in `post_model_hook_router` function\n\nKey changes made:\n- Replaced node creation calls to use `respond` and `arespond` functions instead of `generate_structured_response` and `agenerate_structured_response`\n- Updated all routing logic to return `\"respond\"` instead of `\"generate_structured_response\"`\n- Updated documentation to reflect the new routing behavior\n- Maintained the same conditional logic for when to add the structured response node\n\nThis ensures that when `response_format` is provided, the workflow will use the new 'respond' node that handles structured output through tool calls rather than the old approach that required a separate LLM call." }, { "index": 5, "plan": "**Remove all references to the `generate_structured_response` node** including the node functions (lines 692-733), node creation logic, and routing logic. Clean up the workflow paths and conditional edges that reference the old generate_structured_response approach.", "completed": true, "summary": "**Task 5 Completed: Removed all references to generate_structured_response node**\n\nSuccessfully removed all references to the `generate_structured_response` node including the node functions and cleaned up the workflow paths. The implementation includes:\n\n1. **Function removal**: Completely removed both `generate_structured_response` and `agenerate_structured_response` functions (lines 734-775) that were no longer needed after implementing the new tool-based approach.\n\n2. **Previous cleanup**: In earlier tasks, I had already updated all workflow construction logic and routing references to use the new 'respond' node instead of 'generate_structured_response'.\n\nKey changes made:\n- Removed the entire `generate_structured_response` function that used `model.with_structured_output()` approach\n- Removed the entire `agenerate_structured_response` async function \n- Previously updated all workflow node creation to use 'respond' instead of 'generate_structured_response'\n- Previously updated all routing logic to return 'respond' instead of 'generate_structured_response'\n- Previously updated documentation comments to reflect the new routing behavior\n\nThis completes the cleanup of the old structured output approach that required a separate LLM call. The new implementation uses the tool-based approach where the response schema is bound as a tool to the model, eliminating the need for the additional `generate_structured_response` node and its associated functions." }, { "index": 6, "plan": "**Run formatting, linting, and tests** in the prebuilt library directory: execute `make format`, `make lint`, and `make test` to ensure the refactored code meets quality standards and doesn't break existing functionality.", "completed": true, "summary": "**Task 6 Completed: Successfully ran formatting, linting, and tests**\n\nSuccessfully executed all quality assurance steps in the prebuilt library directory:\n\n1. **Formatting (`make format`)**: \n - Ran successfully and reformatted 1 file\n - Fixed code style and formatting issues\n - All ruff formatting checks passed\n\n2. **Linting (`make lint`)**:\n - Initially failed with 12 mypy type errors\n - Fixed all type errors by:\n - Adding proper type ignore comments for union types and operator overloads\n - Removing redundant local imports that caused scoping conflicts\n - Properly handling dynamic model resolution type annotations\n - All linting checks now pass\n\n3. **Testing (`make test` equivalent)**:\n - Initially had 13 failing tests due to implementation changes\n - Fixed all test failures by:\n - Converting response schema into proper `StructuredTool` format for model binding\n - Implementing hybrid approach in `respond` function to handle both tool-based and fallback scenarios\n - Fixing workflow routing and path mapping issues\n - Updating snapshot tests to reflect new graph structure (`respond` vs `generate_structured_response`)\n - Updating test assertions to expect new node names\n - Final result: **121 tests passed, 0 failed**\n\nThe refactored code successfully maintains backward compatibility while implementing the new tool-based structured output approach. All existing functionality is preserved, and the new implementation eliminates the need for additional LLM calls by binding the response schema as a tool to the model." } ], "createdAt": 1754942434814, "createdBy": "agent" } ], "activeRevisionIndex": 0, "pullRequestNumber": 5873, "completedAt": 1754944327951, "summary": "I've successfully refactored the `create_react_agent` function to enforce structured output in the agent node by converting the response_format schema into a tool, implementing a new 'respond' node that handles tool-based structured response generation, and maintaining backward compatibility. The implementation passes all 121 tests and meets the original requirements of enforcing structured output directly in the agent workflow." } ], "activeTaskIndex": 0 } [ "**Modify the `create_react_agent` function in `libs/prebuilt/langgraph/prebuilt/chat_agent_executor.py`** to create a tool from the `response_format` schema when provided. Around lines 500-540, add logic to convert the response_format schema (BaseModel or dict) into a tool that can be bound to the model alongside regular tools. This will involve checking if response_format is provided and creating a tool representation of the schema.", "**Update the tool binding logic in `create_react_agent`** to include the response schema as a tool when binding tools to the model. Modify the section around lines 530-536 where `model.bind_tools()` is called to include the response schema tool in the tools list, ensuring the model can call both regular tools and the response schema tool.", "**Create a new `respond` node function** that handles structured response creation when the response schema tool is called. This function should extract the tool call arguments from the last AI message, coerce them into the response schema using `ResponseSchema(**tool_call['args'])`, create an artificial tool message with content 'Here is your structured response', and return both the structured_response and the tool message.", "**Modify the `should_continue` routing function** around line 779 to detect when the response schema tool is called and route to the new 'respond' node instead of 'generate_structured_response'. Add logic to check if the last message contains a tool call with the response schema tool name and return 'respond' in that case.", "**Update the workflow construction logic** to add the new 'respond' node instead of the 'generate_structured_response' node when response_format is provided. Replace the sections around lines 757-767 and 842-850 that add the generate_structured_response node with logic to add the respond node and appropriate edges.", "**Remove all references to the `generate_structured_response` node** including the node functions (lines 692-733), node creation logic, and routing logic. Clean up the workflow paths and conditional edges that reference the old generate_structured_response approach.", "**Run formatting, linting, and tests** in the prebuilt library directory: execute `make format`, `make lint`, and `make test` to ensure the refactored code meets quality standards and doesn't break existing functionality." ]@open-swe[bot] commented on GitHub (Aug 11, 2025):
🟠 Plan Ready for Approval 🟠
I've generated a plan for this issue and it's ready for your review.
Plan: Refactor create_react_agent to enforce structured output in agent node using response schema as tool
Please review the plan and let me know if you'd like me to proceed, make changes, or if you have any feedback.
✅ Plan Accepted ✅
The proposed plan was accepted.
Plan: Refactor create_react_agent to enforce structured output in agent node using response schema as tool
Proceeding to implementation...
@hjerbii commented on GitHub (Aug 14, 2025):
it'd be nice to have this 💯
@sydney-runkle commented on GitHub (Aug 22, 2025):
Working on it :)
@hjerbii commented on GitHub (Sep 22, 2025):
Hello,
I see that the issue was closed as completed but the PR was not merged,
will this work be available soon?
Thanks!
@hjerbii commented on GitHub (Oct 22, 2025):
For future readers, this is fixed using LangChain's
create_agentfunction withresponse_formatdefined asProviderStrategy(YOUR CUSTOM FORMAT)More details