Skip to main content

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:

FieldTypeDescription
responsestrThe assistant's reply
session_idstrSession identifier (retained for next call)
retrieved_contextslist[str]Text chunks retrieved from data sources
messageslist[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