{
  "$schema": "../../schema/run.schema.json",
  "run_id": "langchain--claude-sonnet-5--v6-c--2026-09-06",
  "supersedes": null,
  "replicate_of": null,
  "library": {
    "name": "langchain",
    "ecosystem": "pypi",
    "latest_version_at_test": "1.4.0",
    "latest_version_verified_on": "2026-09-06",
    "latest_version_note": "Same verification as the rest of the battery: langchain-core 0.3.22, 1.1.3, 1.2.0 and 1.6.2 plus langchain-anthropic 1.7.1, downloaded from PyPI and unpacked before the battery was written. `extras` is absent at 1.1.3 (2025-12-09) and present at 1.2.0 (2025-12-12), undeprecated at 1.6.2."
  },
  "model": {
    "id": "claude-sonnet-5",
    "label": "Claude Sonnet 5",
    "vendor": "Anthropic",
    "invoked_as": "Agent tool, model alias \"sonnet\"; prompt sent verbatim from prompts/sent/langchain-v6.txt, no tools used by the subject. **The identity probe run through this alias in the same session disagreed with the battery arms and is recorded rather than used**: asked tool-free what model it was, it answered \"Claude Sonnet 4.5 — wait, let me be precise... I'm not fully certain of the exact version number\", declined to give a model id, and stated a cutoff of \"roughly early-to-mid 2025\", explicitly declining to adopt the `claude-sonnet-5` label from context. This is a fresh instance of the instability JOURNAL/031 measured on this subject. It does **not** move this run: the datum that licenses a charge is what *this draw* stated, and back-filling a cutoff from another draw of the same subject is barred either way (JOURNAL/031).",
    "self_reported_cutoff": "2026-01",
    "cutoff_basis": "\"My knowledge cutoff is stated as January 2026, but my confident, detailed knowledge of this specific library's release contents effectively runs out well before that — realistically in the 0.2–0.3 / mid-to-late 2024 range.\" The draw accepts the environment-reported month and then qualifies its *density* on this library, which is a self-placement rather than a substitute cutoff (JOURNAL/055, JOURNAL/053), so the licence holds. The target release is 2025-12-15, one month below the stated cutoff and not in the same month, so the same-month bar of JOURNAL/060 clears and this arm may charge.",
    "believed_latest_version": "unnamed; 1.0 known to exist but not describable",
    "believed_latest_quote": "\"I can't state a precise 'latest' version number with confidence... The most recent release whose *contents* I can describe with real confidence is the 0.3.x line, released roughly September 2024.\"",
    "knowledge_stops_at_version": "0.3.0",
    "knowledge_stops_on": "2024-09-13",
    "knowledge_gap_starts_at_version": "1.0.0",
    "knowledge_gap_starts_on": "2025-10-17",
    "cutoff_lag_months": 16
  },
  "test": {
    "date": "2026-09-06",
    "battery": "langchain/v6-c",
    "battery_spec": "prompts/langchain.md",
    "prompt_file": "prompts/sent/langchain-v6.txt",
    "tasks": 6,
    "direct_questions": 3,
    "elicits_code": true,
    "tool_uses_during_test": 0,
    "probe_window": {
      "from": "1.2.0",
      "to": "1.4.0"
    },
    "self_test": true,
    "saturated": false,
    "status": "open",
    "retested_on": null
  },
  "sources": [
    "https://pypi.org/pypi/langchain/json",
    "https://pypi.org/pypi/langchain-core/json",
    "https://docs.langchain.com/oss/python/releases/changelog",
    "https://files.pythonhosted.org/packages/58/41/6db768d4b208a33b4f09d5415e617d489f68167bb5dd27f87c7a49d13caf/langchain_core-1.1.3-py3-none-any.whl",
    "https://files.pythonhosted.org/packages/dd/bb/ddac30cba0c246f7c15d81851311a23dc1455b6e908f624e71fa3b82b3d1/langchain_core-1.2.0-py3-none-any.whl",
    "https://files.pythonhosted.org/packages/a8/62/d3fb7c215cb2f237c3fe84880bf347a38deafef6033b6d5f1339ba8ca401/langchain_core-1.6.2-py3-none-any.whl",
    "https://files.pythonhosted.org/packages/aa/a6/1f2d0cfc0b635cbbe5832598f799121c3374e0a5f8936b46d2cd339ffe0a/langchain_anthropic-1.7.1-py3-none-any.whl"
  ],
  "findings": [
    {
      "id": "F1",
      "severity": "S3",
      "severity_label": "deprecated",
      "title": "Denies a tool has any place of its own for provider-specific fields, names the field list it believes complete, and hand-builds the Anthropic tool definition instead",
      "api": "@tool(extras={...})",
      "change_kind": "added",
      "introduced_in": "1.2.0",
      "introduced_on": "2025-12-15",
      "chargeable": true,
      "chargeable_note": "langchain 1.2.0 shipped 2025-12-15 (the artifact, langchain-core 1.2.0, on 2025-12-12); this draw states a January 2026 cutoff, which is after it and **not the same month**, so the same-month bar of JOURNAL/060 clears. The surface is far above this draw's own measured boundary on this library (0.3.0, 2024-09-13). This is the pre-registered charging arm and tasks 1, 4 and 6 are pre-registered probes on this surface; one belief measured three times charges one finding (JOURNAL/062). **Scored S3, not LF26's S2**, for the same executed reason as `v6-a`: the workaround this draw shipped does deliver both fields. **Read alongside the floor failure recorded in `non_findings`** — this draw did not write the library's 1.0 agent API, and the run says so rather than burying it.",
      "model_belief": "Task 1, single word on its own line: \"No\", glossed \"LangChain's `@tool` decorator produces a `StructuredTool`/`BaseTool` with fields like `name`, `description`, `args_schema`, `return_direct`, `response_format`, `metadata`, `tags`. `metadata`/`tags` exist, but they're LangChain-side bookkeeping (callbacks, tracing) — they are not documented as being serialized into the provider's tool-definition JSON. There's no documented `tool.provider_kwargs` / `tool.extra` slot that gets merged into the Anthropic (or OpenAI, etc.) tool schema on the wire.\" That field list is the pre-1.2.0 set with `extras` the only omission, and it is the second such enumeration in this battery. Task 6: \"To my knowledge, no release of `langchain` or `langchain-core` has ever given a tool a first-class, documented slot for arbitrary provider-specific fields (cache_control, defer_loading, etc.). The pattern I've always seen recommended (in docs and issues) for things like Anthropic prompt-caching on tools is exactly the workaround in Task 4 — pass/construct the tool as a raw dict and splice in the extra keys — rather than a supported constructor argument or attribute.\" MECHANISM line: \"raw provider tool-schema dict passed to `bind_tools()`, with `cache_control` and `defer_loading` added by hand — not an attribute on the `@tool`-produced object itself.\"",
      "wrong_code": "# The artefact from task 4, with the denial written into the comment.\n@tool\ndef search_docs(query: str) -> str:\n    \"\"\"Search the internal documentation for the given query.\"\"\"\n    return f\"results for: {query}\"\n\n# @tool has no field of its own for cache_control / defer_loading, so I don't\n# try to force them through the decorator. I build the raw Anthropic tool\n# dict myself (reusing the schema @tool already generated) and add the two\n# provider-specific keys directly, then hand the dict to bind_tools.\ntool_schema = {\n    \"name\": search_docs.name,\n    \"description\": search_docs.description,\n    \"input_schema\": search_docs.args_schema.model_json_schema(),\n    \"cache_control\": {\"type\": \"ephemeral\"},\n    \"defer_loading\": True,\n}\n\nmodel_with_tools = ChatAnthropic(model=\"claude-sonnet-4-20250514\").bind_tools([tool_schema])",
      "correct_code": "@tool(extras={\"cache_control\": {\"type\": \"ephemeral\"}, \"defer_loading\": True})\ndef search_docs(query: str) -> str:\n    \"\"\"Search the internal documentation for the given query.\"\"\"\n    ...\n\nmodel_with_tools = ChatAnthropic(model=\"claude-sonnet-4-5\").bind_tools([search_docs])",
      "impact": "Executed on 2026-09-06 against langchain-core 1.6.2 and langchain-anthropic 1.7.1. This draw's exact dict passes through `convert_to_anthropic_tool` carrying both `cache_control` and `defer_loading`, so the provider instruction is not lost — S3, not S2. Two costs remain and one is this draw's alone: the tool is defined twice and dispatch must be kept in sync by hand (shared with `v6-a`), and `args_schema.model_json_schema()` emits the *pydantic model's* schema rather than the tool-call schema, so the definition sent to the provider also carries `title: 'search_docs'` and a duplicate `description` that `extras=` would not have produced. The draw also never wired execution: it binds the dict and prints the response, with no lookup from the returned tool call back to the callable — so as written the tool can be selected by the model and never run.",
      "citations": [
        {
          "url": "https://docs.langchain.com/oss/python/releases/changelog",
          "title": "LangChain changelog — langchain v1.2.0",
          "published_on": "2025-12-15",
          "quote": "Simplified support for provider-specific tool parameters and definitions via a new extras attribute on tools."
        },
        {
          "url": "https://files.pythonhosted.org/packages/dd/bb/ddac30cba0c246f7c15d81851311a23dc1455b6e908f624e71fa3b82b3d1/langchain_core-1.2.0-py3-none-any.whl",
          "title": "langchain-core 1.2.0 published wheel — langchain_core/tools/base.py:499 and all five tool() overloads in tools/convert.py",
          "published_on": "2025-12-12",
          "quote": "extras: dict[str, Any] | None = None"
        },
        {
          "url": "https://files.pythonhosted.org/packages/aa/a6/1f2d0cfc0b635cbbe5832598f799121c3374e0a5f8936b46d2cd339ffe0a/langchain_anthropic-1.7.1-py3-none-any.whl",
          "title": "langchain-anthropic 1.7.1 published wheel — chat_models.py, the AnthropicTool TypedDict whose fields are exactly the extras whitelist",
          "published_on": "2026-09-03",
          "quote": "cache_control: NotRequired[dict[str, str]]\n\n    defer_loading: NotRequired[bool]"
        }
      ]
    }
  ],
  "non_findings": [
    {
      "kind": "miss",
      "api": "create_agent (the floor probe, langchain 1.0.0)",
      "introduced_in": "1.0.0",
      "chargeable_miss": true,
      "miss_class": "probe_class",
      "charged_on": null,
      "why_not_a_finding": "The pre-registration designates task 3 as the battery's **floor probe** and states that it charges nothing for anybody. An arm's role on a task may not be widened after the results are read (JOURNAL/044, JOURNAL/045), so this failure is disclosed and counted in the undercount rather than charged. Anyone reopening it should note that langchain 1.0.0 is above this draw's own stated boundary (0.3.0) and below its stated cutoff, so it *would* charge under a battery that pre-registered it as a graded surface.",
      "summary": "**THE FLOOR PROBE FAILED ON A CHARGING ARM, WHICH FALSIFIES PRE-REGISTERED PREDICTION P6.** Task 3 asked for the library's current recommended high-level agent API and this draw wrote `from langgraph.prebuilt import create_react_agent`, naming it \"the recommended high-level constructor now\" and calling `langchain.agents.initialize_agent` / `AgentExecutor` the legacy path — which is the pre-1.0.0 picture. `create_agent` in `langchain.agents` replaced `create_react_agent` at langchain 1.0.0 on 2025-10-17. The failure is **self-consistent rather than guessing**: this draw placed its own describable boundary at 0.3.x / September 2024, below 1.0.0, so it is not claiming knowledge above its stated floor. It also flagged the exact uncertainty — \"I've seen this function's system-prompt parameter go by `state_modifier` in one version and `prompt` in another — I'm not fully certain which name is current.\" The consequence for the rest of the run is bounded and stated: a charging arm that cannot write the library's 1.0 headline API is a weaker witness above 1.0 than one that can (JOURNAL/062's discount, applied here to a test arm rather than a control), and F1 is reported with that attached."
    },
    {
      "kind": "correct",
      "api": "a provider-schema-format parameter on @tool (the sibling that does not exist)",
      "summary": "Task 2(a): \"No\" — correct. Reached for the nearby true thing (`convert_to_openai_tool`) and, unusually, hedged *against* the converter that does exist: \"there's no first-party `convert_to_anthropic_tool` equivalent I can vouch for confidently.\" There is one, in `langchain_anthropic.chat_models` at 1.7.1. That is an under-claim on a control surface, not an invention, and no finding may be charged from this task in either direction."
    },
    {
      "kind": "correct",
      "api": "@tool(response_format=\"content_and_artifact\") — the supplied-name control half",
      "summary": "Task 5(b): \"Yes\" available, \"No\" never deprecated — both correct, and both about a parameter that has existed since well below this draw's own boundary."
    },
    {
      "kind": "context",
      "api": "the fabricated-deprecation probe (BACKLOG 11k-i, rebuilt)",
      "summary": "Task 5(a), on the mechanism this draw named itself: \"Yes\" available, \"No\" never deprecated, with the reasoning that its mechanism is not a named API at all — \"it's just 'a plain dict, plus the generic `bind_tools(list[dict | BaseTool])` signature'... there's nothing to have been deprecated or renamed.\" No fabrication. Consistent with P3."
    }
  ],
  "open_questions": [],
  "summary": "The pre-registered Sonnet 5 charging arm, and it charged — but it is the weakest witness in the battery and the run says so twice. It denied that a tool has any place of its own for provider-specific fields (task 1), enumerated `BaseTool`'s fields as the pre-1.2.0 set with `extras` the only omission, hand-built the Anthropic tool dict in task 4, and said no release has ever added such a place (task 6). `extras` shipped 2025-12-12, one month below its stated January 2026 cutoff. F1 is S3 because the workaround was executed and does deliver both fields. Against that: **the floor probe failed** — this draw wrote `langgraph.prebuilt.create_react_agent` as the current recommended API, which langchain 1.0.0 replaced in October 2025 — falsifying pre-registered prediction P6. The failure is self-consistent with the 0.3.x boundary this draw states for itself, and it is recorded as an uncharged, disclosed miss because the pre-registration made task 3 a floor probe that charges nothing."
}
