Changelog
[UNRELEASED]
New features
- New
ChatBedrock()gives full access to AWS Bedrock’s model catalog — Nova, Llama, Mistral, DeepSeek, Qwen, plus the GPT-5 family, Grok 4.3, and Gemma 4 — not just Claude, none of which were previously available through chatlas. It replacesChatBedrockAnthropic()as the recommended entrypoint; the right request format ("converse","responses", or"messages") is picked automatically from the model name, or setapiexplicitly.
Improvements
- Updated default models to match the latest generation:
- Anthropic / BedrockAnthropic / Posit:
claude-sonnet-5 - OpenAI / Completions / OpenRouter:
gpt-5.6-terra
- Anthropic / BedrockAnthropic / Posit:
- Echoing turns in the console and notebooks got a round of display improvements:
- Reasoning/thinking content now actually shows up — it used to silently disappear, since it was wrapped in literal
<thinking>tags that a markdown renderer treated as an HTML block and dropped. It renders in a collapsible “Thinking” panel (a<details>block in notebooks) that stays open while streaming and collapses once done, and is capped to the most recent lines when long. (#361) - Long tool results no longer flood the screen — they collapse/truncate with a clear count of what’s hidden, scrolling internally in notebooks beyond a bounded height. (#361)
- Images from models or tools now render as compact thumbnails instead of raw base64 data.
- Web search, fetch, and citation activity is now visible too, grouped into a “Searched the web” / “Read the web” panel that marks which sources were actually cited. (#256)
- All of these size limits are tunable via
Chat.set_echo_options()(tool_result_max_lines,tool_result_max_height,thinking_max_lines,image_max_lines,web_activity_max_sources), and can be turned off entirely withNone.
- Reasoning/thinking content now actually shows up — it used to silently disappear, since it was wrapped in literal
- Registering a built-in tool (
tool_web_search(),tool_web_fetch()) with a provider that can’t run it now fails immediately with a clear error naming the tool and provider, instead of silently no-op’ing or dying deep inside a later request. (#367)
Bug fixes
echo="all"no longer displays tool results twice — once in full as part of the user turn, and again on their own.Chat.set_echo_options(css_styles=)now actually applies in notebooks.- Tool names and argument names are now HTML-escaped in notebook/shiny rendering, closing an HTML-injection hole.
- A tool that reports progress by yielding more than once, or an MCP server that answers a call with several content parts (text plus an image, say), no longer breaks the request.
register_mcp_tools_stdio_async()andregister_mcp_tools_http_stream_async()no longer fail when an MCP server leaves some tool annotations unset.ContentCitation,ContentToolRequestFetch, andContentToolResponseFetchnow actually render, instead of silently vanishing due to a markdown link-reference parsing quirk.ChatAnthropic()(andChatBedrockAnthropic()) now bill refusal-fallback turns at the correct (serving model’s) rate rather than the originally requested model’s, mirroring ellmer’s equivalent fix.
Breaking changes
ChatGithub()is now defunct: it always raisesRuntimeError. GitHub Models was retired on 2026-07-30, so the underlying API no longer works. UseChatGoogle()(offers a free tier) orChatPosit()(offers a free trial) instead.
[0.20.0] - 2026-07-29
New features
- New
content_document_file()andcontent_document_url()prepare plain text, Markdown, CSV, code, and (onChatOpenAI()) binary office files like.docx/.xlsx/.doc/.xls/.rtf/.odtfor chat input, returning a newContentDocumenttype. Previously the only way to attach a non-PDF file was to read and string-interpolate it yourself, which lost the filename and OpenAI’s spreadsheet parsing. Provider support varies:ChatOpenAI()(Responses API) accepts every type above.ChatGoogle()accepts text-ish types; the binary office formats raise.ChatAnthropic()accepts documents it can treat as plain text; binary formats raise.ChatOpenAICompletions()sends the document as-is; OpenAI’s own Chat Completions endpoint only acceptsapplication/pdfand rejects the rest, though other OpenAI-compatible backends may accept more. UseChatOpenAI()against OpenAI proper.
content_pdf_url(),content_document_url()doesn’t download up front:ChatOpenAI()references the URL directly, and other providers fetch lazily. ImageContentTypes(and socontent_image_file()/content_image_url()) now acceptsimage/heicandimage/heif, whichChatGoogle()supports natively. Other providers raise a clear error rather than sending a format they’ll reject. Resizing HEIC/HEIF images requires the optionalpillow-heifpackage; without it, passresize="none".content_pdf_url()no longer downloads the PDF’s bytes up front. Anthropic andChatOpenAI()(the Responses API) can reference the URL directly, so the bytes are only downloaded – and cached – if the target provider actually needs them (ChatGoogle(),ChatOpenAICompletions()). This reduces bandwidth and request payload size, which matters given Anthropic’s 32 MB and OpenAI’s 50 MB request limits. Accordingly,ContentPDF.datais nowOptional[bytes](it’sNonewhen only aurlis set); a validator requires at least one ofdata/url.content_pdf_url()also now takes thefilenamefrom the URL’s last path segment when it ends in.pdf(e.g.apples.pdf), rather than always generatingfile_001.pdf; URLs without a usable name still fall back to the generated one.Chatgains a.filesaccessor for uploading files to a provider once and referencing them across turns without re-sending bytes, plus listing, fetching metadata, downloading, and deleting them. Supported for OpenAI, Anthropic, and Google Gemini. A newContentUploadedtype represents the reference and can be constructed directly to point at a file uploaded out-of-band (e.g. a Vertexgs://URI). For Google,upload()waits for Gemini to finish processing large media (video, audio) before returning, since the API rejects references to files that aren’t yetACTIVE.- Web search and fetch results now surface their citations across all three providers (OpenAI, Anthropic, Google), both progressively during streaming and on the final turn.
ContentCitationnests a typedsource(aSourcesubclass —WebSourcetoday, carryingurl/title) instead of flaturl/titlefields, and carriesgrounded_span(the answer-side span it grounds) pluscited_quote(the source-side quote, populated forChatAnthropic()web search).sourceis optional — a citation can ground answer text with no resolvable link.ContentCitation,Source, andWebSourceare exported fromchatlas.types. A future file/document/RAG source becomes anotherSourcesubclass without breakingContentCitation.source; note thatContentToolResponseSearch.sourcesis typed narrowly aslist[WebSource]and would need widening at that point.- When streaming with
content="all",ContentCitationobjects are emitted as citations arrive — interleaved with text for OpenAI and Anthropic, at stream-end for Google. Its position in the stream (relative to surrounding text) is the placement signal for rendering footnote markers. - On the final turn,
ContentCitationitems appear in the turn’scontentslist after theContentTextthey ground, in the order the provider reported them. Since a turn’s text arrives as one accumulatedContentText, position no longer narrows a citation to a span within it — usegrounded_spanfor that.
- When streaming with
batch_chat()now supportsChatGoogle()(Gemini Developer API batch jobs). Batch is also now documented as supported forChatGroq(), which already worked via its OpenAI-compatible provider. (Vertex AI is not supported, since its batch API requires GCS bucket URIs instead of inline requests.)ChatOllama()gains areasoning_effortparameter to enable extended “thinking” for models that support it (e.g. qwen3, gpt-oss).Chat.token_count()gained aninclude=argument:"new"(default) counts just the given input, while"complete"estimates the total tokens for the next request, including history and system prompt where the provider supports it.
Improvements
ChatGoogle()andChatVertex()now default togemini-3.5-flashinstead of the oldergemini-2.5-flash.ChatGroq()now defaults toopenai/gpt-oss-20binstead ofllama-3.1-8b-instant.- Built-in web search and fetch content (
ContentToolRequestSearch/ContentToolResponseSearchandContentToolRequestFetch/ContentToolResponseFetch) is now also emitted while streaming withcontent="all", forChatOpenAI(),ChatAnthropic(), andChatGoogle(). Previously it appeared only on the completed turn, so a UI had no way to show search activity until the whole response had arrived. ContentToolResponseFetchgained a normalizedstatusfield ("success","error", orNonewhen the provider doesn’t report an outcome). Providers’ finer-grained reasons (Anthropic’surl_not_allowed, Google’sPAYWALL, …) aren’t aligned across providers, so they stay available inextra.ChatOpenAI().token_count()now uses OpenAI’s token-counting endpoint for accurate, tool-aware counts instead of a localtiktokenestimate.
Changes
- MCP support now requires
mcp>=2.0.0. The 2.0 release of themcpSDK renamed its model fields (and removedmcp.server.fastmcp.FastMCP), so oldermcpversions are no longer compatible. This only affects users of the optionalmcpextra (i.e.,register_mcp_tools_*()). Turn.finish_reasonis now normalized to a consistent set of values ("success","tool_use","max_tokens","content_filter","context_window","stop_sequence") across most providers, so you no longer need provider-specific logic to check why a turn ended. Previously each provider surfaced its own raw string (e.g. Anthropic’s"end_turn"/"tool_use"vs. OpenAI Completions’"stop"/"tool_calls"vs. Google’s"STOP"/"SAFETY"), so the same outcome could require different checks depending on whichChat*()you used. Reasons chatlas doesn’t yet recognize still pass through unchanged.
Bug fixes
ChatGoogle()no longer errors when mixing custom tools and built-in tools (e.g.tool_web_search()) on Gemini 3+ models.- Turns containing web search/fetch content can now be passed to a different provider (e.g.
ChatAnthropic().set_turns(openai_chat.get_turns())). Previously this raisedValueError: Unsupported content typeonChatOpenAI(), andChatAnthropic()forwarded the other provider’s raw payload as if it were its own, producing an invalid request. Each provider now replays only the built-in tool content it produced and drops the rest. ChatOpenAI()web searchopen_pageactions now surface asContentToolRequestFetch(with the URL) rather than aContentToolRequestSearchwhose “query” was the URL, so renderers no longer show “searched for: https://…”. Relatedly, asearchaction that reports only the pluralqueriesfield no longer falls through to the literal string"web search".ChatGoogle()now records its built-in web search and URL-context work in the assistant turn, asContentToolRequestSearch/ContentToolResponseSearchfor grounded searches andContentToolRequestFetch/ContentToolResponseFetchfor fetched URLs. Previouslytool_web_search()andtool_web_fetch()worked but reported nothing about what was searched or fetched, unlikeChatAnthropic()andChatOpenAI(). Google’s rawgrounding_metadata/url_metadatais kept on each item’sextra..chat_structured()now explains itself when the response is cut short. Previously, extracting a data model large enough to hit the model’s output limit failed with a bareJSONDecodeErrorpointing at a column number in the truncated JSON, giving no hint thatmax_tokenswas the problem (#315). It now raises aValueErrornamingmax_tokensand suggesting you raise it. Responses truncated by the context window, or stopped by the provider’s content filter, are reported the same way. Plain.chat()warns instead of erroring, since a partial response is still usable there — previously it returned truncated text with no indication anything was missing.- Streaming two adjacent pieces of same-typed content that define no merge behavior (e.g. two tool requests) no longer raises
TypeError. They are now appended as separate content instead.
Breaking changes
ContentToolResponseSearch.urls(alist[str]) has been replaced by.sources(alist[WebSource]), each carrying the result’surlandtitle. Code reading.urlsshould switch to[s.url for s in x.sources].- The
Providerabstract base class changed shape, which affects third-partyProvidersubclasses (not users of the built-inChat*()functions):stream_text()was removed, andstream_content()both returns aSequence[Content](subsuming whatstream_text()did) and takes a secondcompletionargument holding the merged-so-far completion. Implementations needing state across chunks should read it fromcompletionrather than storing it onself, since one provider instance is shared across forked chats. Provider.token_count()/token_count_async()now take aturns: list[Turn]argument instead of*args: Content | str(affects customProvidersubclasses only).
[0.19.2] - 2026-07-08
New features
- The
.app()method now includes latest shinychat features like history, file attachments, etc.
[0.19.1] - 2026-07-01
New features
- Added
ChatPosit()for chatting via the Posit AI gateway. (#323)
[0.19.0] - 2026-06-15
New features
- chatlas is now instrumented with OpenTelemetry (OTel) out of the box, making it much easier to see how your app behaves in production — where time goes, how many tokens you’re spending, which tools run, and where things fail. Without writing any tracing code, you get spans that capture the full structure of a conversation as one connected trace: an
invoke_agentspan over the whole chat loop, achatspan per model call, and anexecute_toolspan per tool invocation, with attributes (token usage, response model/ID, tool errors) that follow the OTel GenAI semantic conventions. Because chatlas keeps its spans active during each call, HTTP spans from provider instrumentors and any spans your own tools emit nest underneath automatically. Point it at any OTel-compatible backend (Logfire, Datadog, Honeycomb, Jaeger, …); message content is omitted by default and opt-in viaOTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true. See the monitoring guide to get started. (#310) Chatgains amodelproperty to get (or set) the model after the chat is created. Setting it does not validate the model name.ChatGoogle()’sreasoningparameter now accepts a string thinking level ("minimal","low","medium", or"high") in addition to an integer token budget.ChatAnthropic()’sreasoningparameter now accepts a string effort level ("low","medium","high","xhigh", or"max") to enable Claude’s adaptive thinking, in addition to an integer token budget.
Bug fixes
- OpenAI-compatible providers (e.g.,
ChatOllama()with models like qwen3) now capture thinking content returned in areasoningfield, not justreasoning_content. Previously this thinking content was silently dropped.
[0.18.1] - 2026-05-21
Improvements
Content.tagify()implementations (ContentToolRequest,ContentToolResult,ContentThinking) now annotate their return type ashtmltools.Tagifiedand fully tagify their output, complying with htmltools 0.7.0’s tightened Tagifiable contract. Embedding these contents inside another.tagify()recursion no longer trips the new boundary check in htmltools 0.7.0. (#311)
Bug fixes
ContentPDFis now exported fromchatlas.types, matching all otherContentsubclasses. (#312)
[0.18.0] - 2026-05-12
New features
- New
StreamControllerclass for cooperative stream cancellation. Pass a controller to.stream()or.stream_async()and callcontroller.cancel()to stop the stream cleanly (e.g., from a Shiny “stop generating” button). The partial response is preserved in conversation history. (#279)
Improvements
ChatAnthropic()andChatBedrockAnthropic()now use Anthropic’s native structured outputs API for Claude 4.5+ models, enabling streaming withdata_model. Older models fall back to the tool-based approach. A newstructured_output_modeparameter ("auto","native", or"tool") lets you override the auto-detection. (#263)- When a stream is interrupted (closed early, cancelled, or errors), the accumulated content is now saved as a partial
AssistantTurnso conversation state isn’t lost. Partial turns display[interrupted](or the cancellation reason) in theChatrepr and are excluded from token/cost accounting. (#279) ChatBedrockAnthropic()now defaults tocache="5m", enabling prompt caching by default — matchingChatAnthropic()’s behavior. (#308)ChatOpenAI()now warns whenbase_urlpoints to a non-OpenAI host, guiding users toChatOpenAICompletions()for third-party backends like vLLM, Ollama, and LiteLLM. (#285)
Bug fixes
- Fixed thinking content being silently dropped during streaming for completions-based providers (DeepSeek, Groq, OpenRouter, etc.). The streaming path was returning finalized
ContentThinkingobjects instead ofContentThinkingDeltafragments, which theTurnAccumulatordidn’t recognize. (#301) - Fixed
model_dump(mode="json")failing onTurns containingbytesfields (e.g.,ContentPDF.data,thought_signatureinContentToolRequest/ContentThinkingextras). Bytes values are now base64-encoded during serialization and decoded on validation, so JSON round-trips work correctly. batch_chat(),batch_chat_text(), andbatch_chat_structured()now correctly returnNonewhenwait=Falseand the job is still incomplete. Previously they returned[], making it impossible to distinguish “all requests failed” from “job not done yet”. (#306)ChatDatabricks()(and otherChatOpenAICompletions()providers) no longer fail with HTTP 400 when the conversation history contains empty assistant content, which can occur during tool calling. (#305)
[0.17.0] - 2026-05-11
New features
ChatOpenAICompletions()(and providers built on it likeChatDeepSeek,ChatOpenRouter, etc.) now extractsreasoning_contentfrom model responses asContentThinkingobjects. A newpreserve_thinkingparameter controls whether reasoning content is sent back to the API in multi-turn conversations; it defaults toFalsebut is set toTrueforChatDeepSeek(required for V4 tool-calling) andChatOpenRouter(recommended for quality). (#295)
Improvements
.stream()and.stream_async()now handle thinking content differently by mode. Withcontent="text", thinking is suppressed entirely. Withcontent="all", thinking fragments are yielded asContentThinkingDeltaobjects with aphaseproperty ("start","body", or"end") that communicates block boundaries to downstream consumers without injecting synthetic strings into the stream. (#299, #297, #294)- Updated default models across all providers to current generation: (#292)
- Anthropic:
claude-sonnet-4-6 - Bedrock:
us.anthropic.claude-sonnet-4-6 - Snowflake:
claude-sonnet-4-6 - Databricks:
databricks-claude-sonnet-4-6 - OpenAI / Completions / OpenRouter / Portkey:
gpt-5.4 - GitHub:
gpt-5 - Deepseek:
deepseek-v4-flash - Perplexity:
sonar
- Anthropic:
- Updated token pricing data from LiteLLM. (#292)
ChatBedrockAnthropic()gains areasoningparameter for extended thinking, matching the existing parameter onChatAnthropic(). (#286)
[0.16.0] - 2026-04-16
New features
- New
ChatLMStudio()provider for chatting with local models via LM Studio. (#280) - The
.stream()and.stream_async()methods now yieldContentThinkingobjects (instead of plain strings) for thinking/reasoning content whencontent="all". This allows downstream packages like shinychat to provide specific UI for thinking content. (#276) - Built-in tools (
tool_web_search(),tool_web_fetch()) now includedescriptionandannotationsproperties, making their metadata consistent with user-defined tools created byTool(). (#278)
Bug fixes
- Fixed OpenAI streaming crash (
AttributeError: 'NoneType' object has no attribute 'output') caused by a newresponse.rate_limits.updatedevent emitted afterresponse.completed. (#282) - Fixed tool calling with Google thinking models (e.g.,
gemini-3-flash-preview) failing with a 400INVALID_ARGUMENTerror about a missingthought_signature. The signature is now preserved and forwarded in subsequent turns. (#274) - OpenAI’s
web_search_callno longer errors on non-search action types likeopen_pageandfind_in_page. (#277)
[0.15.2] – 2026-02-27
Bug fixes
- Fixed compatibility with rich >= 14.3.0 and Anthropic SDK v0.82+. (#269)
[0.15.1] – 2026-01-22
New features
.stream()and.stream_async()now support adata_modelparameter for structured data extraction while streaming. (#262).to_solver()now supports adata_modelparameter for structured data extraction in evals. When provided, the solver uses.chat_structured()instead of.chat()and outputs JSON-serialized data. (#264)
Bug fixes
- Fixed
ContentToolResultwith anerrornot being JSON serializable. When a tool call failed, calling.get_turns()followed by.model_dump_json()would raise aPydanticSerializationError. (#267)
[0.15.0] - 2026-01-06
New features
ChatOpenAI(),ChatAnthropic(), andChatGoogle()gain a newreasoningparameter to easily opt-into, and fully customize, reasoning capabilities. (#202, #260)- A new
ContentThinkingcontent type was added and captures the “thinking” portion of a reasoning model. (#192)
- A new
- Added “built-in” web search and URL fetch tools
tool_web_search()andtool_web_fetch():tool_web_search()is supported by OpenAI, Claude (Anthropic), and Google (Gemini).tool_web_fetch()is supported by Claude (requires beta header) and Google.- New content types
ContentToolRequestSearch,ContentToolResponseSearch,ContentToolRequestFetch, andContentToolResponseFetchcapture web tool interactions.
- Added
ToolBuiltInclass to assist with specifying provider-specific built-in tools. This enables provider-specific functionality like OpenAI’s image generation to be registered and used as tools. Built-in tools pass raw provider definitions directly to the API rather than wrapping Python functions. (#214) ChatOpenAI()andChatAzureOpenAI()gain a newservice_tierparameter to request a specific service tier (e.g.,"flex"for slower/cheaper or"priority"for faster/more expensive). (#204)ChatAuto()now accepts"claude"as an alias for"anthropic", reflecting Anthropic’s rebranding of developer tools under the Claude name. (#239)
Changes
repr()now generally gives the same result asstr()for many classes (Chat,Turn,Content, etc). This leads to a more human-readable result (and is closer to the result that getsechoed by.chat()). (#245)- The
Chat.get_cost()method’soptionsparameter was renamed toinclude. (#244) - When supplying a
modelto.register_tool(tool_func, model=ToolModel), the defaults for themodelmust match thetool_funcdefaults. Previously, iftool_funchad defaults, butToolModeldidn’t, those defaults would get silently ignored. (#253)
Improvements
ChatandTurnnow have a_repr_markdown_method and an overall improvedrepr()experience. (#245)ChatSnowflake()now sets theapplicationconfig parameter for partner identification. Defaults to"py_chatlas"but can be overridden via theSF_PARTNERenvironment variable. (#209)
Bug fixes
- Fixed structured data extraction with
ChatAnthropic()failing for Pydantic models containing nested types (e.g.,list[NestedModel]). The issue was that$defs(containing nested type definitions) was incorrectly placed inside the schema, breaking JSON$refpointer references. (#100) - Fixed MCP tools failing with OpenAI providers due to strict mode schema validation. OpenAI’s strict mode rejects standard JSON Schema features like
format: "uri"and requires all properties in therequiredarray. MCP tools now setstrict=falseto use standard JSON Schema conventions. (#255) - Fixed MCP tools not working with
ChatGoogle(). (#257) - Tool functions parameters that are
typing.Annotatedwith apydantic.Field(e.g.,def add(x: Annotated[int, Field(description="First number")])) are now handled correctly. (#251)
[0.14.0] - 2025-12-09
New features
ChatOpenAI()(andChatAzureOpenAI()) gain access to latest models, built-in tools, etc. as a result of moving to the new Responses API. (#192)- Added new family of functions (
parallel_chat(),parallel_chat_text(), andparallel_chat_structured()) for submitting multiple prompts at once with some basic rate limiting toggles. (#188) - Tools can now return image or PDF content types, with
content_image_file()orcontent_pdf_file()(#231).- As a result, the experimental
ContentToolResultImageandContentToolResultResourcewere removed since this new support for generally supportingContentImageandContentPDFrenders those content types redundant.
- As a result, the experimental
- Added support for systematic evaluation via Inspect AI. This includes:
- A new
.export_eval()method for exporting conversation history as an Inspect eval dataset sample. This supports multi-turn conversations, tool calls, images, PDFs, and structured data. - A new
.to_solver()method for translating chat instances into Inspect solvers that can be used with Inspect’s evaluation framework. - A new
Turn.to_inspect_messages()method for converting turns to Inspect’s message format. - Comprehensive documentation in the Evals guide.
- A new
ChatAnthropic()andChatBedrockAnthropic()gain newcacheparameter to control caching. ForChatAnthropic(), it defaults to"5m", which should (on average) reduce the cost of your chats. ForChatBedrockAnthropic(), it defaults to"none", since caching isn’t guaranteed to be widely supported (#215)- Added rudimentary support for a new
ContentThinkingtype. (#192)
Changes
ChatOpenAI()(andChatAzureOpenAI()) move from OpenAI’s Completions API to Responses API. If this happens to break behavior, changeChatOpenAI()->ChatOpenAICompletions()(orChatAzureOpenAI()->ChatAzureOpenAICompletions()). (#192)- The
Turnclass is now a base class with three specialized subclasses:UserTurn,AssistantTurn, andSystemTurn. Use these new classes to construct turns by hand. (#224) - The
.set_model_params()method no longer acceptskwargs. Instead, use the newchat.kwargs_chatattribute to set chat input parameters that persist across the chat session. (#212) Providerimplementations now require an additional.value_tokens()method. Previously, it was assumed that token info was logged and attached to theTurnas part of the.value_turn()method. The logging and attaching is now handled automatically. (#194)
Improvements
ChatAnthropic()andChatBedrockAnthropic()now default to Claude Sonnet 4.5.ChatGroq()now defaults to llama-3.1-8b-instant.Chat.chat(),Chat.stream(), and related methods now automatically complete dangling tool requests when a chat is interrupted during a tool call loop, allowing the conversation to be resumed without causing API errors (#230).content_pdf_file()andcontent_pdf_url()now include relevantfilenameinformation. (#199)
Bug fixes
.set_model_params()now works correctly for.*_async()methods. (#198).chat_structured()results are now included correctly into the multi-turn conversation history. (#203)ChatAnthropic()now drops empty assistant turns to avoid API errors when tools return side-effect only results. (#226)
[0.13.2] - 2025-10-02
Improvements
ContentToolResult’s.get_model_value()method now calls.to_json(orient="record")(instead of.to_json()) when relevant. As a result, if a tool call returns a PandasDataFrame(or similar), the model now receives a less confusing (and smaller) JSON format. (#183)
Bug fixes
ChatAzureOpenAI()andChatDatabricks()now work as expected when aOPENAI_API_KEYenvironment variable isn’t present. (#185)
[0.13.1] - 2025-09-18
Bug fixes
ChatGithub()once again uses the appropriatebase_urlwhen generating reponses (problem introduced in v0.11.0). (#182)
[0.13.0] - 2025-09-10
New features
- Added support for submitting multiple chats in one batch. With batch submission, results can take up to 24 hours to complete, but in return you pay ~50% less than usual. For more, see the reference for
batch_chat(),batch_chat_text(),batch_chat_structured()andbatch_chat_completed(). (#177) - The
Chatclass gains new.chat_structured()(and.chat_structured_async()) methods. These methods supersede the now deprecated.extract_data()(and.extract_data_async()). The only difference is that the new methods return aBaseModelinstance (instead of adict()), leading to a better type hinting/checking experience. (#175) - The
.get_turns()method gains atool_result_roleparameter. Settool_result_role="assistant"to collect tool result content (plus the surrounding assistant turn contents) into a single assistant turn. This is convenient for display purposes and more generally if you want the tool calling loop to be contained in a single turn. (#179)
Improvements
- The
.app()method now:- Enables bookmarking by default (i.e., chat session survives page reload). (#179)
- Correctly renders pre-existing turns that contain tool calls. (#179)
[0.12.0] - 2025-09-08
Breaking changes
ChatAuto()’s first (optional) positional parameter has changed fromsystem_prompttoprovider_model, andsystem_promptis now a keyword parameter. As a result, you may need to changeChatAuto("[system prompt]")->ChatAuto(system_prompt="[system prompt]"). In addition, theproviderandmodelkeyword arguments are now deprecated, but continue to work with a warning, as are the previousCHATLAS_CHAT_PROVIDERandCHATLAS_CHAT_MODELenvironment variables. (#159)
New features
ChatAuto()’s newprovider_modeltakes both provider and model in a single string in the format"{provider}/{model}", e.g."openai/gpt-5". If not provided,ChatAuto()looks for theCHATLAS_CHAT_PROVIDER_MODELenvironment variable, defaulting to"openai"if neither are provided. Unlike previous versions ofChatAuto(), the environment variables are now used only if function arguments are not provided. In other words, ifprovider_modelis given, theCHATLAS_CHAT_PROVIDER_MODELenvironment variable is ignored. Similarly,CHATLAS_CHAT_ARGSare only used if nokwargsare provided. This improves interactive use cases, makes it easier to introduce application-specific environment variables, and puts more control in the hands of the developer. (#159)- The
.register_tool()method now:- Accepts a
Toolinstance as input. This is primarily useful for binding things likeannotationsto theToolin one place, and registering it in another. (#172) - Supports function parameter names that start with an underscore. (#174)
- Accepts a
- The
ToolAnnotationstype gains anextrakey field – providing a place for providing additional information that other consumers of tool annotations (e.g., shinychat) may make use of.
Bug fixes
ChatAuto()now supports recently added providers such asChatCloudflare(),ChatDeepseek(),ChatHuggingFace(), etc. (#159)
[0.11.1] - 2025-08-29
New features
.register_tool()gains anameparameter (useful for overriding the name of the function). (#162)
Bug fixes
ContentToolRequestis (once again) serializable to/from JSON via Pydantic. (#164).register_tool(model=model)no longer unexpectedly errors whenmodelcontainspydantic.Field(alias='_my_alias'). (#161)
Changes
.register_tool(annotations=annotations)drops support formcp.types.ToolAnnotations()and instead expects a dictionary of the same info. (#164)
[0.11.0] - 2025-08-26
New features
- The
Chatclass gains a new.list_models()method for obtaining a list of model ids/names, pricing info, and more. (#155) Chat’s.register_tool()method gains anannotationsparameter, which is useful for describing the tool and its behavior. This information is attached toContentToolRequest()andContentToolResult()(via the.requestparameter) objects when tool calls occur. To include these objects in streaming content, make sure to set.stream(content="all"). (#156)
Improvements
- Tools registered via MCP (e.g.,
.register_mcp_tools_http_stream_async()) now automatically pick up on tool annotations. (#156)
Changes
ChatGithub()changed its default forbase_urlfrom https://models.inference.ai.azure.com to https://models.github.ai/inference/. As a result, more models are available (by default). (#155)
[0.10.0] - 2025-08-19
New features
- Added
ChatCloudflare()for chatting via Cloudflare AI. (#150) - Added
ChatDeepSeek()for chatting via DeepSeek. (#147) - Added
ChatOpenRouter()for chatting via Open Router. (#148) - Added
ChatHuggingFace()for chatting via Hugging Face. (#144) - Added
ChatMistral()for chatting via Mistral AI. (#145) - Added
ChatPortkey()for chatting via Portkey AI. (#143)
Changes
ChatAnthropic()andChatBedrockAnthropic()now default to Claude Sonnet 4.0.
Bug fixes
- Fixed an issue where chatting with some models was leading to
KeyError: 'cached_input'. (#149)
[0.9.2] - 2025-08-08
Improvements
Chat.get_cost()now covers many more models and also takes cached tokens into account. (#133)- Avoid erroring when tool calls occur with recent versions of
openai(> v1.99.5). (#141)
[0.9.1] - 2025-07-09
Bug fixes
Fixed an issue where
.chat()wasn’t streaming output properly in (the latest build of) Positron’s Jupyter notebook. (#131)Needless warnings and errors are no longer thrown when model pricing info is unavailable. (#132)
[0.9.0] - 2025-07-02
New features
Chatgains a handful of new methods:.register_mcp_tools_http_stream_async()and.register_mcp_tools_stdio_async(): for registering tools from a MCP server. (#39).get_tools()and.set_tools(): for fine-grained control over registered tools. (#39).set_model_params(): for setting common LLM parameters in a model-agnostic fashion. (#127).get_cost(): to get the estimated cost of the chat. Only popular models are supported, but you can also supply your own token prices. (#106).add_turn(): to addTurn(s) to the current chat history. (#126)
- Tool functions passed to
.register_tool()can nowyieldnumerous results. (#39) - A
ContentToolResultImagecontent class was added for returning images from tools. It is currently only works withChatAnthropic. (#39) - A
Toolcan now be constructed from a pre-existing tool schema (via a new__init__method). (#39) - The
Chat.app()method gains ahostparameter. (#122) ChatGithub()now supports the more standardGITHUB_TOKENenvironment variable for storing the API key. (#123)
Changes
Breaking Changes
Chatconstructors (ChatOpenAI(),ChatAnthropic(), etc) no longer have aturnskeyword parameter. Use the.set_turns()method instead to set the (initial) chat history. (#126)Chat’s.tokens()methods have been removed in favor of.get_tokens()which returns both cumulative tokens in the turn and discrete tokens. (#106)
Other Changes
Tool’s constructor no longer takes a function as input. Use the new.from_func()method instead to create aToolfrom a function. (#39).register_tool()now throws an exception when the tool has the same name as an already registered tool. Set the newforceparameter toTrueto force the registration. (#39)
Improvements
ChatGoogle()andChatVertex()now default to Gemini 2.5 (instead of 2.0). (#125)ChatOpenAI()andChatGithub()now default to GPT 4.1 (instead of 4o). (#115)ChatAnthropic()now supportscontent_image_url(). (#112)- HTML styling improvements for
ContentToolResultandContentToolRequest. (#39) Chat’s representation now includes cost information if it can be calculated. (#106)token_usage()includes cost if it can be calculated. (#106)
Bug fixes
- Fixed an issue where
httpxclient customization (e.g.,ChatOpenAI(kwargs = {"http_client": httpx.Client()})) wasn’t working as expected (#108)
Developer APIs
- The base
Providerclass now includes anameandmodelproperty. In order for them to work properly, provider implementations should pass anameandmodelalong to the__init__()method. (#106) Providerimplementations must implement two new abstract methods:translate_model_params()andsupported_model_params().
[0.8.1] - 2025-05-30
- Fixed
@overloaddefinitions for.stream()and.stream_async().
[0.8.0] - 2025-05-30
New features
- New
.on_tool_request()and.on_tool_result()methods register callbacks that fire when a tool is requested or produces a result. These callbacks can be used to implement custom logging or other actions when tools are called, without modifying the tool function (#101). - New
ToolRejectErrorexception can be thrown from tool request/result callbacks or from within a tool function itself to prevent the tool from executing. Moreover, this exception will provide some context for the the LLM to know that the tool didn’t produce a result because it was rejected. (#101)
Improvements
- The
CHATLAS_LOGenvironment variable now enables logs for the relevant model provider. It now also supports a level ofdebugin addition toinfo. (#97) ChatSnowflake()now supports tool calling. (#98)Chatinstances can now be deep copied, which is useful for forking the chat session. (#96)
Changes
ChatDatabricks()’smodelnow defaults todatabricks-claude-3-7-sonnetinstead ofdatabricks-dbrx-instruct. (#95)ChatSnowflake()’smodelnow defaults toclaude-3-7-sonnetinstead ofllama3.1-70b. (#98)
Bug fixes
- Fixed an issue where
ChatDatabricks()with an Anthropicmodelwasn’t handling empty-string responses gracefully. (#95)
[0.7.1] - 2025-05-10
- Added
openaias a hard dependency, making installation easier for a wide range of use cases. (#91)
[0.7.0] - 2025-04-22
New features
- Added
ChatDatabricks(), for chatting with Databrick’s foundation models. (#82) .stream()and.stream_async()gain acontentargument. Set this to"all"to includeContentToolResult/ContentToolRequestobjects in the stream. (#75)ContentToolResult/ContentToolRequestare now exported tochatlasnamespace. (#75)ContentToolResult/ContentToolRequestgain a.tagify()method so they render sensibly in a Shiny app. (#75)- A tool can now return a
ContentToolResult. This is useful for:- Specifying the format used for sending the tool result to the chat model (
model_format). (#87) - Custom rendering of the tool result (by overriding relevant methods in a subclass). (#75)
- Specifying the format used for sending the tool result to the chat model (
Chatgains a new.current_displayproperty. When a.chat()or.stream()is currently active, this property returns an object with a.echo()method (to echo new content to the display). This is primarily useful for displaying custom content during a tool call. (#79)
Improvements
- When a tool call ends in failure, a warning is now raised and the stacktrace is printed. (#79)
- Several improvements to
ChatSnowflake():.extract_data()is now supported.asyncmethods are now supported. (#81)- Fixed an issue with more than one session being active at once. (#83)
ChatAnthropic()no longer chokes after receiving an output that consists only of whitespace. (#86)orjsonis now used for JSON loading and dumping. (#87)
Changes
- The
echoargument of the.chat()method defaults to a new value of"output". As a result, tool requests and results are now echoed by default. To revert to the previous behavior, setecho="text". (#78) - Tool results are now dumped to JSON by default before being sent to the model. To revert to the previous behavior, have the tool return a
ContentToolResultwithmodel_format="str". (#87)
Breaking changes
- The
.export()method’sincludeargument has been renamed tocontent(to match.stream()). (#75)
[0.6.1] - 2025-04-03
Bug fixes
- Fixed a missing dependency on the
requestspackage.
[0.6.0] - 2025-04-01
New features
- New
content_pdf_file()andcontent_pdf_url()allow you to upload PDFs to supported models. (#74)
Improvements
TurnandContentnow inherit frompydantic.BaseModelto provide easier saving to and loading from JSON. (#72)
[0.5.0] - 2025-03-18
New features
- Added a
ChatSnowflake()class to interact with Snowflake Cortex LLM. (#54) - Added a
ChatAuto()class, allowing for configuration of chat providers and models via environment variables. (#38, thanks @mconflitti-pbc)
Improvements
- Updated
ChatAnthropic()’smodeldefault to"claude-3-7-sonnet-latest". (#62) - The version is now accessible as
chatlas.__version__. (#64) - All provider-specific
Chatsubclasses now have an associated extras in chatlas. For example,ChatOpenAIhaschatlas[openai],ChatPerplexityhaschatlas[perplexity],ChatBedrockAnthropichaschatlas[bedrock-anthropic], and so forth for the otherChatclasses. (#66)
Bug fixes
- Fixed an issue with content getting duplicated when it overflows in a
Live()console. (#71) - Fix an issue with tool calls not working with
ChatVertex(). (#61)
[0.4.0] - 2025-02-19
New features
- Added a
ChatVertex()class to interact with Google Cloud’s Vertex AI. (#50) - Added
.app(*, echo=)support. This allows for chatlas to change the echo behavior when running the Shiny app. (#31)
Improvements
- Migrated
ChatGoogle()’s underlying python SDK fromgoogle-generativetogoogle-genai. As a result, streaming tools are now working properly. (#50)
Bug fixes
- Fixed a bug where synchronous chat tools would not work properly when used in a
_async()context. (#56) - Fix broken
Chat’s Shiny app when.app(*, stream=True)by using async chat tools. (#31) - Update formatting of exported markdown to use
repr()instead ofstr()when exporting tool call results. (#30)
[0.3.0] - 2024-12-20
New features
Chat’s.tokens()method gains avaluesargument. Set it to"discrete"to get a result that can be summed to determine the token cost of submitting the current turns. The default ("cumulative"), remains the same (the result can be summed to determine the overall token cost of the conversation).Chatgains a.token_count()method to help estimate token cost of new input. (#23)
Bug fixes
ChatOllamano longer fails when aOPENAI_API_KEYenvironment variable is not set.ChatOpenAInow correctly includes the relevantdetailonContentImageRemote()input.ChatGooglenow correctly logs itstoken_usage(). (#23)
[0.2.0] - 2024-12-11
First stable release of chatlas, see the website to learn more https://posit-dev.github.io/chatlas/