posit-dev / posit-dev/chatlas

Prompt "profiles": serializable bundles of system prompt + tools + schema

Open
#349 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

ai-triage:needs-review enhancement
Dominant language
Python
Stars
176
Forks
28
Avg merge
18h 42m
Merged PRs (30d)
16

Description

Motivation

Simon Willison's llm has templates: YAML bundles of system prompt, prompt fragments, model options, tools, and schemas, invoked via llm -t name. This lets users package up a reusable "agent config" and share it as a file. chatlas has the pieces (interpolate()/interpolate_file() in chatlas/_interpolate.py, register_tool()/set_tools() and chat_structured(data_model=...) in chatlas/_chat.py, set_model_params()), but nothing that bundles them into one serializable, shareable unit. Pydantic AI has a related but narrower idea in reusable Agent instances, though those aren't declaratively serializable either.

Proposed approach

Introduce a Profile object — a thin, serializable bundle of the inputs to a Chat, not a new execution engine:

from chatlas import Profile, ChatOpenAI

profile = Profile(
    system_prompt="You are a terse SQL assistant.\n{{ extra_instructions }}",  # interpolate() template
    data_model="myapp.schemas.SqlAnswer",  # optional, import-path string
    params={"temperature": 0.2},
)

chat = profile.create_chat(ChatOpenAI, variables={"extra_instructions": "Always cite the table."})
  • Profile.from_yaml(path) / Profile.to_yaml(path) (or TOML) for round-tripping.
  • system_prompt is rendered through interpolate() at create_chat() time, so the same template mechanics/variable-inference already in _interpolate.py apply.
  • data_model and params map directly onto chat_structured(data_model=...) and set_model_params().
  • Tools are the hard part. Functions aren't YAML-serializable. Two honest options: (a) store an import path string ("myapp.tools:lookup_price") resolved via importlib at load time — simple, but ties the profile to code being importable in the same environment; (b) require a small in-app registry mapping names to callables that the profile references by name only. Given this complexity, the proposal is to ship the non-tool subset first (system prompt + data_model + params, dumpable/loadable), and treat tool bundling as a stretch goal / separate follow-up once the serialization approach is validated with users.

Alternatives / prior art

  • ellmer has interpolate() (string-only) and no bundling concept beyond that — this would be new territory for both projects, so getting the design right in chatlas first and porting later (as usual) seems reasonable.
  • Do nothing: users keep hand-rolling a dict/module of prompt+schema+params, which works but isn't shareable as a file the way llm's templates are.
  • A pure-YAML "recipe" that only ever produces kwargs for ChatAuto(**kwargs) (no new class) is a lighter-weight alternative worth considering.

Open questions

  • Is create_chat() the right entry point, or should this be a Chat*(profile=...) constructor kwarg instead (per the original ask)?
  • YAML vs TOML vs both?
  • Should Profile also carry the provider/model string (à la ChatAuto's "provider/model"), or stay provider-agnostic and let the caller pick the Chat* class?

Drafted from a competitive review of llm / Pydantic AI / LangChain / LiteLLM (July 2026); filed via Claude Code on behalf of @cpsievert.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading chatlas/_interpolate.py and chatlas/_chat.py, especially interpolate(), chat_structured(), set_model_params(), and the tool methods. Resolve the open questions around serialization scope and the creation entry point, then verify that a Profile can round-trip its system_prompt, data_model, and params and create a Chat with interpolation. Tool bundling is outside the initial done criteria.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.