Assistant & App
The Assistant and App classes give you the most control over the assistant lifecycle. Use them when you need to configure an assistant programmatically or reuse a configuration across multiple deploys.
Assistant
A configurable assistant object. Call methods to build it up, then call .deploy() to get a live App.
Constructor
from custodian_labs import Assistant
assistant = Assistant(
model="gpt-4o",
system_prompt="You are a helpful legal research assistant.",
api_key=None, # falls back to CUSTODIAN_SDK_API_KEY env var
base_url=None, # falls back to CUSTODIAN_SDK_BASE_URL env var
timeout=30.0,
max_retries=2,
)
.add_examples(examples)
Attach few-shot examples. Accepts an iterable of dicts with "user" and "assistant" keys. Returns self for chaining.
assistant.add_examples([
{
"user": "What does force majeure mean?",
"assistant": "Force majeure is a contract clause that excuses a party from performance when extraordinary events prevent fulfillment.",
}
])
.add_data_source_file(path)
Upload a local file as a RAG knowledge source. The file is parsed, split into 800-character chunks (120-character overlap), and embedded with OpenAI text-embedding-3-small. At chat time, the top relevant chunks are retrieved by cosine similarity and injected into the LLM context. Supported formats: TXT, PDF, DOCX, XLS, XLSX. Returns self for chaining.
assistant.add_data_source_file("./contracts/template-library.pdf")
.deploy()
Deploy the configured assistant and return an App.
app = assistant.deploy()
.chat(message)
Shortcut that deploys (if not already deployed) and immediately sends a message. Returns a ChatResponse.
response = assistant.chat("Summarize the key clauses in a standard NDA.")
App
Represents a deployed assistant endpoint. Obtain one from assistant.deploy(), AssistantBuilder.deploy(), or create_assistant().
.chat(message)
Send a message and get a response. Session state is retained automatically — subsequent calls continue the same conversation thread.
response = app.chat("What topics does this handbook cover?")
print(response.response)
print(response.retrieved_contexts) # chunks used from data sources
print(response.session_id)
ChatResponse fields:
| Field | Type | Description |
|---|---|---|
response | str | The assistant's reply |
session_id | str | Session identifier (retained for next call) |
retrieved_contexts | list[str] | Text chunks retrieved from data sources |
messages | list[dict] | Full conversation history |
.chat() — interactive mode
Call .chat() with no argument to enter an interactive CLI session:
app.chat()
# Interactive chat mode. Type 'exit' or 'quit' to stop.
# You: ...
.reset_session()
Clear the retained session, starting fresh on the next .chat() call.
app.chat("My name is Jordan.")
app.reset_session()
app.chat("What's my name?") # Starts a new session — no memory of "Jordan"
.session_id
The current session ID, or None if no messages have been sent yet.
print(app.session_id) # "session_abc123" or None
Full example
from custodian_labs import Assistant
assistant = (
Assistant(model="gpt-4o", system_prompt="You are an HR policy assistant.")
.add_examples([
{"user": "How do I request time off?", "assistant": "Submit a request through the HR portal at least 5 days in advance."}
])
.add_data_source_file("./employee-handbook.pdf")
)
app = assistant.deploy()
print(app.chat("What is the remote work policy?").response)
print(app.chat("And what about international travel?").response) # continues same session