ClimateClaw Client
A Python client library for interacting with the ClimateClaw backend. This library provides both synchronous and asynchronous interfaces for communicating with a ClimateClaw chatbot instance.
Features:
- Synchronous client (
ClimateClaw) with full API support - Asynchronous client (
AsyncClimateClaw) with full API support - OIDC authentication via py-oidc-auth-client
- Thread management (create, retrieve, list, search, fork, and delete conversation threads)
- Streaming and non-streaming prompt responses
- Thread operations (stop active conversations, set thread topics, edit/fork threads)
- User feedback (submit positive/negative feedback on assistant messages)
- Rich message types with markdown rendering support
Requirements
- Python 3.10+
Dependencies
httpx- HTTP client for making requestspydantic- Data validation and message modelingpy_oidc_auth_client- OIDC authentication handling
Installation
Currently, this package is in development and must be installed from source:
git clone https://github.com/freva-org/climateclaw-client.git
cd climateclaw-client
pip install -e .
Or using uv:
uv pip install -e .
Usage
Initialization
from climateclaw_client.client import ClimateClaw
# Create a client instance
cc = ClimateClaw(
base_url="https://your-climate-claw-backend.com",
token_store_path="~/.cache/climateclaw-client/token-store.json", # Optional: path to store auth tokens
)
# Authenticate with the backend (triggers OIDC flow)
cc.authenticate()
Available Models
# List available chatbot models
models = cc.available_models
print(f"Available models: {models}")
# Set a default model for the client
cc.model = "gpt-4.1"
Prompting the Backend
Non-streamed Response
# Send a prompt and get the complete conversation
conversation = cc.prompt(
"Please calculate the average temperature over Germany for the years 1990-2020!"
)
# Render the entire answer as a human-readable string
print(conversation)
# Access the individual messages
for message in conversation.messages:
print(f"{message.variant}: {message.content}")
# Get markdown representation
markdown = conversation.repr_markdown()
print(markdown)
Streamed Response
# Send a prompt with streaming enabled
stream_conv = cc.prompt(
"Please explain the ENSO phenomenon to me and give examples of how to quantify it!", stream=True
)
# Iterate over markdown-ready chunks as they arrive
with stream_conv as stream:
for markdown_chunk in stream.iter_for_markdown():
print(markdown_chunk)
# After streaming completes, access the full conversation
full_conversation = stream_conv.translate_to_conversation()
print(full_conversation.repr_markdown())
Thread Management
Create a New Thread
# Create a new conversation thread
thread_id = cc.newthread()
print(f"New thread ID: {thread_id}")
Get a Thread
# Retrieve an existing thread by ID
thread_id = "your-thread-id"
conversation = cc.getthread(thread_id=thread_id)
# Or use the current active thread
conversation = cc.getthread()
# Print all messages
print(conversation)
Prompt in a Specific Thread
# Continue a conversation in an existing thread
response = cc.prompt(
"Please explain how the SOI can be calculated and run an example analysis.",
thread_id=thread_id, # optional: uses thread of active conversation otherwise
)
List User Threads
# List all your conversation threads
total_threads, user_threads = cc.getuserthreads(num_threads=10)
print(f"A total number of {total_threads} threads was retrieved.")
# access individual threads (which are Conversation objects)
print(user_threads[0])
Search Threads
# Search for threads by topic
total_results, matching_threads = cc.searchthreads(query="climate analysis", num_threads=5)
Set Thread Topic
# Set a topic for a thread (useful for searching later)
cc.setthreadtopic("ENSO analysis", thread_id=thread_id)
Delete a Thread
# Delete a thread on the backend when you're done with it
cc.deletethread(thread_id=thread_id)
Working with Message Types
The client provides rich message types that can be rendered in different formats:
from climateclaw_client.client import ClimateClaw
# Create a client instance
cc = ClimateClaw(base_url="https://your-climate-claw-backend.com")
# Authenticate with the backend
cc.authenticate()
# List available models
print(f"Available models: {cc.available_models}")
cc.model = cc.available_models[0]
# Start a conversation
response = cc.prompt(
"Show me a code example of using the xarray library for analysing climate data!"
)
# Access individual messages
initial_response = response[0]
# String representation (for Python sessions)
print(str(initial_response))
# Markdown representation (for rendering)
print(initial_response.repr_markdown())
# Access content directly
print(initial_response.content)
# Extract code cells from Assistant messages
for code_cell in initial_response.message.code_cells:
print(f"Code cell: {code_cell}")
Handling Images
Image messages have special methods:
# If the response contains an image
if response.messages[1].variant == "Image":
image_message = conversation.messages[1]
# Get markdown representation (base64 embedded)
md = image_message.repr_markdown()
# Save to file
image_message.save_to_file("output.png")
Raw Message Access
# Access raw message chunks (before aggregation)
response = cc.prompt("Hello ClimateClaw! What is your function?")
for raw_msg in conversation.raw_messages:
print(raw_msg.message.variant)
print(raw_msg.message.content)
Message Types
The library supports the following message variants:
| Variant | Description | Special Methods |
|---|---|---|
Prompt |
Initial user prompt | repr_content(), repr_markdown() |
User |
User message | repr_content(), repr_markdown() |
Assistant |
Assistant response | code_cells property, repr_content(), repr_markdown() |
Code |
Python code | code_cells property, repr_markdown() renders as code block |
CodeOutput |
Code execution output | repr_markdown() renders as blockquote |
Image |
Base64-encoded image | repr_markdown(), save_to_file() |
ServerError |
Server error message | repr_content(), repr_markdown() |
OpenAIError |
OpenAI error message | repr_content(), repr_markdown() |
CodeError |
Code execution error | repr_content(), repr_markdown() |
StreamEnd |
Stream completion marker | repr_markdown() |
ServerHint |
Backend hint data (such as server heartbeats) | repr_markdown() |
Asynchronous Client
The library includes an AsyncClimateClaw class for async operations, providing the same functionality as the synchronous client but with async/await syntax:
import asyncio
from climateclaw_client import AsyncClimateClaw
async def main():
# Create an async client instance
cc = AsyncClimateClaw(
base_url="https://your-climate-claw-backend.com",
token_store_path="~/.cache/climateclaw-client/token-store.json",
)
# Authenticate with the backend
await cc.authenticate()
# List available models
print(f"Available models: {cc.available_models}")
cc.model = cc.available_models[0]
# Send a prompt
response = await cc.prompt(
"Please calculate the average temperature over Germany for 1990-2020!"
)
print(response)
# Send a streaming prompt
stream_resp = await cc.prompt("Please explain the ENSO phenomenon to me!", stream=True)
async with stream_resp as stream:
async for markdown_chunk in stream.aiter_for_markdown():
print(markdown_chunk)
# Thread management
thread_id = await cc.newthread()
response = await cc.prompt(
"Please explain how the SOI can be calculated.",
thread_id=thread_id,
)
# Run the async main function
asyncio.run(main())
Note: The async client uses httpx.AsyncClient under the hood and provides all the same methods as the synchronous ClimateClaw client, but as coroutines that must be awaited.
Configuration Options
| Parameter | Type | Default | Description |
|---|---|---|---|
base_url |
str/URL | Required | Base URL of the ClimateClaw backend |
token_store_path |
str | "" | Path to store OIDC tokens |
follow_redirects |
bool | True | Whether to follow HTTP redirects |
timeout |
float | 30.0 | Request timeout in seconds |
max_retries |
int | 3 | Maximum retry attempts for failed requests |
http_client |
httpx.Client / httpx.AsyncClient | None | Pre-configured HTTP client (Optional) |
thread_id |
str | None | Default thread ID for conversations |
model |
str | None | Default model for prompts |
Note: For AsyncClimateClaw, the http_client parameter should be an httpx.AsyncClient instance, while for ClimateClaw it should be an httpx.Client instance.
Project Links
- Source Code: https://github.com/freva-org/climateclaw-client
- Backend Repository: https://github.com/freva-org/climateclaw
- Documentation: https://climate-claw-client.readthedocs.io/latest/
- Issue Tracker: https://github.com/freva-org/climateclaw-client/issues
License
This project is licensed under the European Union Public Licence 1.2 (EUPL-1.2).
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file climateclaw_client-0.2.0.tar.gz.
File metadata
- Download URL: climateclaw_client-0.2.0.tar.gz
- Upload date:
- Size: 37.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a12088af1b2314fc60e39ff0a120119da70ccb71796145149cf1f223979c2d42
|
|
| MD5 |
34cb128bbeff1aab1fb1ed5ba2dc7d75
|
|
| BLAKE2b-256 |
aec2b3ecf187942b92d87b832affe1b46630a38d84122670df7a459ad7ec6ced
|
Provenance
The following attestation bundles were made for climateclaw_client-0.2.0.tar.gz:
Publisher:
publish.yml on freva-org/climateclaw-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
climateclaw_client-0.2.0.tar.gz -
Subject digest:
a12088af1b2314fc60e39ff0a120119da70ccb71796145149cf1f223979c2d42 - Sigstore transparency entry: 2408038656
- Sigstore integration time:
-
Permalink:
freva-org/climateclaw-client@aad13e825f7316a285a8d65af74e0877ae8eeb8b -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/freva-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aad13e825f7316a285a8d65af74e0877ae8eeb8b -
Trigger Event:
push
-
Statement type:
File details
Details for the file climateclaw_client-0.2.0-py3-none-any.whl.
File metadata
- Download URL: climateclaw_client-0.2.0-py3-none-any.whl
- Upload date:
- Size: 10.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a7bee15dd34bede42012b1d577246ff9fb17a37e56568ab5a2d70d593ef0ccb
|
|
| MD5 |
b690f2b5ecafc54907e13174683498e1
|
|
| BLAKE2b-256 |
03bdec8b0116a50268a44f177de866f7ba728191d6d4f1890ef2b565a1573710
|
Provenance
The following attestation bundles were made for climateclaw_client-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on freva-org/climateclaw-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
climateclaw_client-0.2.0-py3-none-any.whl -
Subject digest:
4a7bee15dd34bede42012b1d577246ff9fb17a37e56568ab5a2d70d593ef0ccb - Sigstore transparency entry: 2408039551
- Sigstore integration time:
-
Permalink:
freva-org/climateclaw-client@aad13e825f7316a285a8d65af74e0877ae8eeb8b -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/freva-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aad13e825f7316a285a8d65af74e0877ae8eeb8b -
Trigger Event:
push
-
Statement type: