Skip to main content

chatsnack

chatsnack is the easiest Python library for rapid development with OpenAI's ChatGPT API. It provides an intuitive interface for creating and managing chat-based prompts and responses, making it convenient to build complex, interactive conversations with AI.

Documentation site

For typed judgments over existing data, use Samplers and reusable Questions, included with chatsnack 0.9.0.

chatsnack features

Setup

Got snack?

Install the chatsnack package from PyPI:

# requires Python 3.11+
pip install chatsnack

Got keys?

Add your OpenAI API key to your .env file. If you don't have a .env file, the library will create a new one for you in the local directory.

Learn More!

Read more below, watch the intro video or check out the Getting Started notebook.

Responses API Support

Chat() now defaults to the Responses family over WebSocket with session="inherit". If you stay on that default path--or explicitly choose another Responses transport-- chatsnack requires the OpenAI Python client to be openai>=3.5.0,<4.0.0. For explicit WebSocket support outside chatsnack's packaged dependencies, install openai[realtime]>=3.5.0,<4.0.0.

Using OpenRouter, Azure v1, or another OpenAI-compatible endpoint? See the OpenAI-compatible providers guide.

Using GPT-6? See the model compatibility notes for supported reasoning efforts, Responses tool calling, and migration warnings.

Usage

Enjoy a Quick Snack

Easiest way to get going with chatsnack is with built-in snack packs. Each pack is a singleton ready to mingleton.

>>> from chatsnack.packs import ChatsnackHelp
>>> ChatsnackHelp.ask("What is your primary directive?")

"My primary directive is to assist users of the chatsnack Python module by answering questions and helping with any problems or concerns related to the module. I aim to provide helpful and informative responses based on the chatsnack module's documentation and best practices."

You can try out other example snack packs like Confectioner, Jolly, Chester, Jane, or Data. (Eventually there will be an easy way to create and share your own.)

Instead of .ask() we can call .chat() which will allow us to continue a conversation.

>>> mychat = ChatsnackHelp.chat("What is chatsnack?")  # submits and returns a new chat object
>>> print(mychat.response)

Chatsnack is a Python module that provides a simple and powerful interface for creating conversational agents and tools using OpenAI's ChatGPT language models. It allows you to easily build chat prompts, manage conversation flow, and integrate with ChatGPT to generate responses. With Chatsnack, you can create chatbots, AI-assisted tools, and other conversational applications using a convenient and flexible API.

Now we can add more messages to that chat however we'd like:

>>> mychat.user("Respond in only six word sentences from now on.")
>>> mychat.asst("I promise I will do so.")
>>> mychat.user("How should I spend my day?")
>>> mychat.ask()

"Explore hobbies, exercise, connect with friends."

If you want a super simple interactive conversation with you and a chatbot, you could do something like this:

from chatsnack.packs import Jolly
yourchat = Jolly  # interview a green giant
while (user_input := input("Chat with the bot: ")):
    print(f"USER: {user_input}")
    yourchat = yourchat.chat(user_input)
    print(f"THEM: {yourchat.last}")

Natural Attachments (Phase 3 style ergonomics)

For the default Responses workflows, you can pass attachments directly at query time with files= and images=:

from chatsnack import Chat

chat = Chat("Review the attachment and answer tersely.")
print(chat.ask("Summarize these.", files=["./images/chart.png", "./data/sales.csv"]))

thread = chat.chat("What stands out in this chart?", files=["./images/chart.png"])
thread = thread.chat("Now compare that with this report.", files=["./data/q2-report.pdf"])
print(thread.last)

When attachments are present, chatsnack stores the user turn as an expanded YAML block (text + files / images) while keeping plain text turns scalar-first.

Generated outputs stay on the continued Chat. .images gives us image ChatFile values, and .files includes every returned file. A ChatFile can be passed into another chat. Captured files can also be read or copied; remote-only references keep their provider metadata but do not have local bytes. Saved chats keep a small local asset reference in YAML. When moving one, take the configured chatsnack data folder with it.

Utensils (Tools)

Local Python functions and hosted OpenAI tools share one utensils=[...] surface:

from chatsnack import Chat, utensil

# Local function tools use the @utensil decorator
@utensil
def get_weather(location: str, unit: str = "celsius"):
    """Get the current weather for a location."""
    return {"temperature": 72, "condition": "sunny", "unit": unit}

# Grouped tools form searchable namespaces
crm = utensil.group("crm", "CRM tools for customer lookup.")

@crm
def get_customer(customer_id: str):
    """Look up one customer by ID."""
    return {"id": customer_id}

# Hosted tools are small named specs
docs_search = utensil.web_search(domains=["docs.python.org"], sources=True)

# Everything passes through utensils=[]
chat = Chat(
    "Use tools only when useful.",
    utensils=[get_weather, crm, utensil.tool_search, docs_search],
)
chat.reasoning.summary = "auto"

The sources=True on web_search automatically populates params.responses["include"] without manual dict mutation.

See the Utensils guide for more information.

For unusually long local-utensil workflows, auto_feed controls the automatic execute-and-follow-up loop. Leave it unset (or use True / None) for the legacy five-cycle limit. A positive integer allows that many cycles; False or 0 still executes the first pending batch, but does not feed its results back to the model. Parallel calls requested in one assistant response count as one cycle.

Tasty Features

There's many other tidbits covered in the notebooks, examples, and videos. Here are some of the highlights:

  • Everyday Snacking
    • Chat objects
    • Chat command chaining
    • YAML convenience
    • OpenAI parameters
  • Serious Snacking
    • Intense chaining
    • Fillings (e.g. nested chats and text files)
    • Snack Pack Vending Machine

Everyday Snacking

Chat objects and Chaining

from chatsnack import Chat
mychat = Chat()
mychat.system("Respond only with the word POPSICLE from now on.")
mychat.user("What is your name?")
mychat.ask()

"POPSICLE."

You can chain messages together for more complex conversations:

newchat = (
  Chat()
  .system("Respond only with the word POPSICLE from now on.")
  .user("What is your name?")
  .chat()
)
newchat.response

"POPSICLE."

Note that there are some syntax shortcuts omitted above, see the Serious Snacking section for more on those.

Yummy YAML

Generative AI gets a bit messy these days with so much text in our code. chatsnack makes it very easy to use a clean YAML syntax to load/save/edit your chat templates without so many hard-coded strings in your code.

# Every chat is totally yaml-backed, we can save/load/edit
print(newchat.yaml)
print(newchat.snapshot.path)
messages:
  - system: Respond only with the word POPSICLE from now on.
  - user: What is your name?
  - assistant: POPSICLE.

For rapid reuse, you can give your chats a name so you can save/load as needed (or using them as Fillings as we'll see later).

newchat.name = "Popsicle"
newchat.save()
print(newchat.snapshot.text)
# Load a chat from a file
midnightsnack = Chat(name="popsicle")
print(midnightsnack.ask())

"POPSICLE."

Adjusting Cooking Temperatures

By default, chatsnack uses the Responses API over WebSocket and gpt-4-turbo. If you prefer, you can change OpenAI parameters for each chat, such as the model and temperature:

from chatsnack import Chat
wisechat = Chat("Respond with professional writing based on the user query.")
wisechat.user("Author an alliterative poem about good snacks to eat with coffee.")
wisechat.model = "gpt-4"
wisechat.temperature = 0.8

This also gets captured in the YAML:

print(wisechat.yaml)
params:
  model: gpt-4
  temperature: 0.8
messages:
  - system: Respond with professional writing based on the user query.
  - user: Author an alliterative poem about good snacks to eat with coffee.

Serious Snacking

Ingredient Shortcuts

If you're wanting to minimize typing, you can use omit a couple of ingredients.

Quick System Message

For example, this:

mychat = Chat()
mychat.system("Respond hungrily")

is the same as:

# if there's only one argument or a keyword of system argument, you can omit the .system()
mychat = Chat("Respond hungrily")
Quick User Message

.ask() and .chat() are also shortcuts for .user().ask() and .user().chat() respectively. For example, this:

mychat = Chat()
mychat.system("Respond hungrily")
mychat.user("Tell me about cookies")
print(mychat.ask())

is the same as:

print(Chat("Respond hungrily").ask("Tell me about cookies"))

Basically, we assume if you're making a Chat() you'll need a system message, and if you're sending an ask() or chat() you'll need a user message. So you can omit those if you want (or use system= and user= keywords if you want to be explicit).

Quick Assistants

Also, .asst() is an alias shortcut for .assistant() if you want you code to align cleanly with other 4-letter .user() and .chat() calls.

Binge-chaining

If you're feeling wild, you can actually call any chat (like a function) and it'll submit the chat and continue, just like .chat(). This allows even more terse chaining. This can come in handy when you're looking for chain-of-thought prompting or prewriting priming.

popcorn = (
    Chat("Respond with the certainty and creativity of a professional writer.")
    ("Explain 3 rules to writing a clever poem that amazes your friends.") 
    ("Using those tips, write a scrumptious poem about popcorn.")
)
# the above is the same as Chat().system('Respond...').chat('Explain...').chat('Using...')
print(popcorn.response)

In the kitchen, I hear a popping sound, A symphony of kernels dancing around. A whiff of butter, a sprinkle of salt, My taste buds tingle, it's not their fault.

The popcorn pops, a fluffy delight, A treat for the senses, a feast for the sight. Golden and crispy, a perfect snack, A bowl of happiness, there's no going back.

I pick one up, it's warm to the touch, I savor the flavor, it's too much. A burst of butter, a crunch of salt, A symphony of flavors, it's not my fault.

I munch and crunch, it's such a delight, A scrumptious treat, a popcorn flight. A perfect snack, for any time, Popcorn, oh popcorn, you're simply divine.

Nested Chats

You can include other chats in your current chat or use {chat.___} filling expander for more dynamic AI generations:

basechat = Chat(name="ExampleIncludedChat").system("Respond only with the word CARROTSTICKS from now on.")
basechat.save()

anotherchat = Chat().include("ExampleIncludedChat")

Snacks with Fillings

You can work with Text files and YAML files to create reusable chat snippets that are filled-in before execution.

from chatsnack import Text
mytext = Text(name="SnackExplosion", content="Respond only in explosions of snack emojis and happy faces.")
mytext.save()

explosions = Chat(name="SnackSnackExplosions").system("{text.SnackExplosion}")
explosions.ask("What is your name?")

Fillings Resolving in Parallel

If you have a prompt that requires expanding multiple fillings, chatsnack will resolve them in parallel as it expands the prompt. This comes in handy with {chat.__} and {vectorsearch.__} (TODO) snack fillings.

See the Fillings and Composition guide for reusable text, saved chats, and direct filling resolution.

License

chatsnack is released under the MIT License.

Metadata

Release files for chatsnack 0.9.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for chatsnack 0.9.2
File Size Uploaded
chatsnack-0.9.2.tar.gz 142.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for chatsnack 0.9.2
File Interpreter ABI Platform
chatsnack-0.9.2-py3-none-any.whl Python 3 none any Details

Total release size: 303.5 kB

Release files / chatsnack-0.9.2.tar.gz

Download URL chatsnack-0.9.2.tar.gz
Size 142.7 kB
Tags Source
SHA-256 checksum
How to use checksums
dd63acdb6d7ce8001647cab0acbd7f4070e52168e085702afa6543b46eed8fc4
BLAKE2b-256 checksum
How to use checksums
41fb176fdc00e2db01a49de9742def0469e0969ae1581384898c9e7247c54401
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release files / chatsnack-0.9.2-py3-none-any.whl

Download URL chatsnack-0.9.2-py3-none-any.whl
Size 160.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5fb6cfa132071b92939e6a019c77dff66c2e0ea076c29dac39481a0e9fa5ff8b
BLAKE2b-256 checksum
How to use checksums
01dc2ff50d2ef789b0e42bd81955da8819bae4dc4b9069c94a88b1bc2c13fe4a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.9.2 This release

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.4

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.1

2 release files

0.1.0

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page