Skip to content

Update Python Server SDK tech docs - #667

Open
hey-august wants to merge 23 commits into
mainfrom
august-20260904-update-python
Open

Update Python Server SDK tech docs#667
hey-august wants to merge 23 commits into
mainfrom
august-20260904-update-python

Conversation

@hey-august

Copy link
Copy Markdown
Collaborator

Description

Sync the Python Server SDK reference to signalwire-python 3.3.0.

  • Add Messages and Projects REST resources, RequestOptions, paginate(), and SignalWireRestTransportError
  • Remove the Twilio-compatibility REST namespace (client.compat) and redirect its URLs to the REST overview
  • Add typed Relay Call convenience methods (play_*, detect_*, prompt_*, wait_for_*)
  • Add HandoffRouter, client capabilities helpers, and post-prompt normalization
  • Add AgentBase.mount, add_per_call_config, handle_request, set_multilingual, on_call_end, swaig_secret
  • Add ContextBuilder set_history, gather isolated, and new validate() checks
  • Reframe FunctionResult response as a prompt to the model; add set_tool_response and hold routing
  • Sync env vars, CLI flags, and helpers with 3.3.0
  • Normalize the Python reference: X | None types, default="None" on optional params, ## **Parameters** headings

Follow-up

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Code cleanup / refactor

Related Issues

Testing

  • yarn fern-md-check passes
  • yarn fern-check passes apart from the unauthenticated redirects check
  • Every parameter, default, return type, and behavior claim verified against SDK source at 7f11951

Checklist

  • I have read the CONTRIBUTING guidelines
  • My code follows the project's style guidelines
  • I have added tests for my changes (if applicable)
  • I have updated documentation (if applicable)
  • All existing tests pass

Additional Notes

hey-august and others added 19 commits September 6, 2026 03:13
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tool response

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ingual, swaig_secret

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

@hey-august hey-august changed the title Update Python SDK tech docs Update Python Server SDK tech docs Sep 8, 2026

@Devon-White Devon-White left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: verified against signalwire-python @ f7fec89 (v3.4.1)

I pulled the SDK fresh. It has moved two releases past this PR's sync point: v3.4.0 (2026-08-24) and v3.4.1 (2026-09-06). Per the 3.4.0 changelog, "3.3.0 was never tagged or documented, so its contents are folded in here" — so the 3.3.0 surface this PR documents is real, but there is post-3.3.0 drift.

What I verified as correct

Method-by-method against source, plus an automated signature/default sweep:

  • HandoffRouter — all 5 methods, ctor defaults nonce_ttl=3600 / max_messages_per_call=200 / capture_timeout=8.0 (ai_chat/handoff.py:92-94), route status codes, NonceEntry exported from signalwire.ai_chat.
  • AgentBase.mount (core/mixins/web_mixin.py:229), add_per_call_config (:1500), on_call_end (core/agent_base.py:557), set_multilingual (core/mixins/ai_config_mixin.py:228).
  • FunctionResulthold() incl. the isinstance(prompt, int) back-compat branch and the bare-integer-unless-routing emission (core/function_result.py:518-594), set_tool_response, rpc_ai_message ValueError, rpc_ai_global_data.
  • core.capabilities and core.post_prompt — including the voice/chat divergence table, which matches the module docstring verbatim.
  • ContextBuilder.validate() — the new initial_step, reserved-name, and dangling-set_functions checks, incl. RESERVED_NATIVE_TOOL_NAMES = {next_step, change_context, gather_submit} (core/contexts.py:1243).
  • Env vars — all 9 new names exist in source; SIGNALWIRE_TOKEN has 0 hits, SIGNALWIRE_API_TOKEN has 18, so the builtin-skills.mdx fix is right.
  • RESTRequestOptions fields/defaults, the POST/PATCH retry asymmetry (rest/_request_options.py:138-160), PaginatedIterator's empty-page and cycle-guard behavior, Messages/Projects, client.compat genuinely gone, SignalWireClientRestClient (rest/__init__.py), area_codeareacode (confirmed against specs/signalwire-rest/relay-rest/phone-numbers/main.tsp:111), and client.calling really is 37 methods.

Automated param-name/default comparison found zero mismatches across 54 relay Call pages, 76 AgentBase pages, and 51 FunctionResult pages. Every newly added /docs/… link and #anchor fragment resolves. yarn fern-md-check passes (2790 files); yarn fern-check fails only the unauthenticated FDR redirects check, as noted in the PR body. No changelog entry — correct, this is documentation work. Nav needs no edit (folder-based). The branch touches no specs/, so there's no build:specs obligation.

Findings

9 inline comments below. Three are post-3.3.0 SDK drift, one is a substantive accuracy bug, the rest are consistency/wording.

Two items I couldn't anchor inline

Both files are outside this PR's diff:

reference/python/agents/cli/sw-search.mdx needs the same two fixes as search/helpers.mdx:

  • Lines 105 and 194 say "spacy" is "Better quality, slower." The SDK deleted that claim in 3.4.1 — see the inline comment on search/helpers.mdx.
  • --min-chunk-size is missing entirely (cli/build_search.py:256), and --chunk-size gained markdown-specific semantics the page doesn't mention. The SDK's own hand-maintained help text now reads: "Chunk size in words (default: 50). For the markdown strategy this is the split threshold, applied as chunk_size * 6 characters." The implementation is min_chars = max(0, self.min_chunk_size * 6) at search/document_processor.py:476.

reference/python/agents/swaig-function/{execute,to-swaig}.mdx have the same normalization gap as the two gather pages: execute(raw_data) and to_swaig(token, call_id) are X | None = None in source but carry no default in the docs.

One process note

The branch is behind origin/main, so this PR's diff currently shows ~200 files it doesn't own (specs/**/tsp-output, fern/apis/*/openapi.yaml, changelog entries, scripts/). The branch's actual authored surface is 296 files, all under fern/products/server-sdks/pages/reference/python/** plus 3 guides, fern/docs.yml, and sdk-source-sync.json. Merging main again would make this much easier to review.

Comment thread fern/products/server-sdks/sdk-source-sync.json Outdated
Comment thread fern/products/server-sdks/pages/reference/python/agents/search/helpers.mdx Outdated
Comment thread fern/products/server-sdks/pages/reference/python/rest/paginate.mdx Outdated
hey-august and others added 4 commits September 9, 2026 14:48
Address the PR #667 review. Post-3.3.0 drift: add min_chunk_size to
IndexBuilder, DocumentProcessor, and sw-search; note chunk_size as the
markdown split threshold; replace the retracted "better quality" spacy
claim with the SDK's measure-it wording. Accuracy: keyword_weight is
accepted and ignored; escalate() returning True doesn't confirm a
captured record; paginate lists the eight list()-only resources.
Normalize optional params on the gather, execute, and to_swaig pages.
Point sdk-source-sync.json at v3.4.1 (the previous commit was a
squash-merged branch head that no longer exists upstream).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@Devon-White Devon-White left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of the Python Server SDK resync. Links, the two new compat redirects, nav globs, and all 15 new EndpointSchemaSnippet/EndpointResponseSnippet references all check out. Findings are inline.

Wrong or contradictory for the reader

  • phone_numbers.search(quantity=...) in three places; the parameter is max_results per openapi.yaml and the Python search reference page.
  • The wait_for_ringing / wait_for_answered examples wait on a call client.dial() already returned answered, so neither shows the method doing anything and the ringing page prints answered.
  • builtin-skills.mdx now says SIGNALWIRE_API_TOKEN for the datasphere fallback while the TypeScript datasphere reference still says SIGNALWIRE_TOKEN.
  • agent-base/handle-request.mdx documents dict[str, Any] where swml-service/handle-request.mdx says dict[str, str] for the same inherited method.

Mechanical

  • Five code-fence highlight ranges are off, including one out of range ({9-15} on a 14-line block).
  • projects.get / projects.delete are missing ## **Parameters**; delete is also missing ## **Returns**.
  • Four new cards inserted out of slug-alphabetical order.

Unrelated to this PR: the broken link /docs/apis/rest/ai-chat/chat-methods in ai-chat-client/index.mdx:9 is pre-existing and untouched — noting it only so it isn't attributed here.


# Search for available numbers in area code 512
available = client.phone_numbers.search(area_code="512", quantity=3)
available = client.phone_numbers.search(areacode="512", quantity=3)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quantity isn't a parameter on phone number search. openapi.yaml line 9599 and reference/python/rest/phone-numbers/search.mdx:27 both use max_results, so this example fails as written.

Suggested change
available = client.phone_numbers.search(areacode="512", quantity=3)
available = client.phone_numbers.search(areacode="512", max_results=3)

Same issue twice in guides/manage-resources/overview.mdx.

available = client.phone_numbers.search(
area_code="512",
areacode="512",
quantity=5,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quantitymax_results, same as reference/python/rest/overview.mdx:46.

Suggested change
quantity=5,
max_results=5,


# Search for a local number
available = client.phone_numbers.search(area_code="512", quantity=1)
available = client.phone_numbers.search(areacode="512", quantity=1)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Third occurrence of quantity on phone number search.

Suggested change
available = client.phone_numbers.search(areacode="512", quantity=1)
available = client.phone_numbers.search(areacode="512", max_results=1)

dialed = await client.dial(
devices=[[{"type": "phone", "params": {"to_number": "+15551234567", "from_number": "+15559876543"}}]]
)
await dialed.wait_for_ringing(timeout=10)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example can't demonstrate what the page documents. client.dial() resolves only once the call is answered, so wait_for_ringing() on the returned call returns immediately and the print("Ringing:", dialed.state) below prints answered, not ringing.

Showing wait_for_ringing needs a call object that hasn't reached ringing yet — a non-blocking dial/connect — or the page should say the state is already past ringing.

dialed = await client.dial(
devices=[[{"type": "phone", "params": {"to_number": "+15551234567", "from_number": "+15559876543"}}]]
)
await dialed.wait_for_answered(timeout=30)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same construction as wait-for-ringing.mdx: client.dial() already returns an answered call, so this wait_for_answered(timeout=30) is a no-op and doesn't show the method doing anything. Worth reworking alongside the ringing page.

<Card title="get_app" href="/docs/server-sdks/reference/python/agents/agent-base/get-app">
Get the FastAPI application instance for use with deployment adapters.
</Card>
<Card title="handle_request" href="/docs/server-sdks/reference/python/agents/agent-base/handle-request">

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: handle_request is out of slug-alphabetical order relative to the rest of the list.

<Card title="get_basic_auth_credentials" href="/docs/server-sdks/reference/python/agents/swml-service/get-basic-auth-credentials">
Retrieve the HTTP Basic Auth credentials for the service.
</Card>
<Card title="handle_request" href="/docs/server-sdks/reference/python/agents/swml-service/handle-request">

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: new card inserted out of the list's slug-alphabetical order.

<Card title="set_functions" href="/docs/server-sdks/reference/python/agents/context-builder/step/set-functions">
Set which SWAIG functions are available during this step.
</Card>
<Card title="set_history" href="/docs/server-sdks/reference/python/agents/context-builder/step/set-history">

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: new card inserted out of the list's slug-alphabetical order.


<EndpointSchemaSnippet endpoint="GET /api/projects/{id}" />

## **Response Example**

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

projects.get takes a required id, but there's no ## **Parameters** section documenting it. projects.delete has the same gap.

Delete a subproject.

<EndpointSchemaSnippet endpoint="DELETE /Accounts/{AccountSid}/Calls/{Sid}" />
<EndpointSchemaSnippet endpoint="DELETE /api/projects/{id}" />

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing two sections relative to the reference page convention: no ## **Parameters** for the required id, and no ## **Returns**. This file was renamed from compat/calls/delete.mdx, so it may have inherited the old page's shape.

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.

2 participants