Skip to content

docs(think): move developer content out of the LLM-facing docstring (#320) - #549

Open
Ashutosh0x wants to merge 1 commit into
strands-agents:mainfrom
Ashutosh0x:docs/320-think-tool-spec-docstring
Open

docs(think): move developer content out of the LLM-facing docstring (#320)#549
Ashutosh0x wants to merge 1 commit into
strands-agents:mainfrom
Ashutosh0x:docs/320-think-tool-spec-docstring

Conversation

@Ashutosh0x

Copy link
Copy Markdown

Addresses task 1 of #320 (@notowen333: "Clean up doc strings in community tools ... Task 1 is eligible for community contribution"), starting with the think tool that @jsgsamzn used as the reproducer.

Problem

ToolSpec.description is built by _extract_description_from_docstring (strands-py/src/strands/tools/decorator.py), which strips only the Args block - its own docstring says it preserves "Returns, Raises, Examples, and other sections". So Python usage examples, STRANDS_* environment variable docs, internal "How It Works" steps and developer notes all ship to the model on every request.

Measured on main by replicating that function against the current sources:

tool description approx tokens Python examples reach the LLM
think 6,017 chars ~1,500 yes
swarm 5,423 chars ~1,355 yes
graph 3,511 chars ~877 yes
shell 1,721 chars ~430 no

shell is the outlier because it already does the right thing - developer usage lives in the module docstring, and the @tool docstring is written for the model. That is Solution 1 from the issue, and this PR applies it to think.

Change

Purely a docstring reorganisation in src/strands_tools/think.py:

  • Moved to the module docstring - "Usage with Strands Agent" Python examples, "How It Works", "Model Selection Process", "Common Usage Scenarios", the STRANDS_* configuration block, and the developer notes. Nothing is deleted; it moves to where a developer reading the source will still find it.
  • Kept in the @tool docstring - what the tool does, when a model should reach for it, the recursion constraint, all eight Args, and Returns.

Result: tool_spec description 6,017 -> 598 characters (-90%), with no Python examples and no environment variables left in it.

Parameter descriptions are unaffected. They are parsed separately into inputSchema via param_descriptions, so the model keeps full per-argument documentation - this only removes the prose the model was never meant to read.

While moving it I also fixed a broken snippet: the old thinking_system_prompt=Use Socratic questioning method: example was missing its quotes.

Validation

  • ast.parse clean
  • All 8 signature parameters still documented, no phantom entries (checked programmatically against the signature, so inputSchema is byte-identical)
  • Before/after description sizes measured by replicating _extract_description_from_docstring exactly
  • No test asserts on this docstring (tests/test_think.py has no description/tool_spec/__doc__ references)

I could not install strands-agents in my environment to render the real tool_spec, so the figures above come from replicating the extraction function rather than executing the decorator. Worth a sanity check in review, though the parity check on the signature means inputSchema cannot have shifted.

Scope

Deliberately one tool. swarm and graph have the same problem and I am happy to extend this PR to both, but the exact voice of an LLM-facing docstring is a judgement call and it seemed better to agree the shape on one tool first than to send three at once. Say the word and I will add them.

The @tool docstring becomes the tool_spec description sent to the model on
every request. think's docstring carried Python usage examples, environment
variable documentation, internal "How It Works" steps and developer notes,
all of which reached the LLM.

Move that content to the module docstring, matching the pattern shell.py
already uses, and keep the @tool docstring focused on what the model needs
to decide whether and how to call the tool. No code or behavior changes; all
eight parameters remain documented, so inputSchema is unaffected.

tool_spec description: 6017 -> 598 characters.

Refs strands-agents#320.
@Ashutosh0x
Ashutosh0x requested a review from a team as a code owner July 29, 2026 03:25
@Ashutosh0x
Ashutosh0x requested review from Unshure and Copilot and removed request for Copilot July 29, 2026 03:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant