Quickly create, version and manage Assistants through LangGraph SDK - an in-depth explanation of how to use the same graph and different configurable parameters to create multiple sets of isolated business assistants.
AssistantIt is a concept provided by LangGraph Platform: it binds "Graph" and "Configuration" together, persists them in PostgreSQL, and allocates a uniqueassistant_id。
One sentence to understand:The same picture + different config = different Assistant。
The task_mAIstro application uses the same picture and passes differenttodo_category("personal" / "work") andtask_maistro_roleCreate two independent ToDo assistants without interfering with each other.
Assistants are defined internally in the dependency graphconfigurable field. task_mAIstro picture inconfiguration.pyThree configurable fields are declared in and read within the node:
# configuration.py(简化)
from dataclasses import dataclass, field
from langgraph.config import get_configurable
@dataclass
class Configuration:
user_id: str = "default_user"
todo_category: str = "general" # "personal" | "work" | ...
task_maistro_role: str = "" # 系统提示词中的角色说明
# 在图节点内读取
config = Configuration(**get_configurable())
The diagram itself does not solidify the business logic, but passesconfigurableFields receive runtime parameters. This allows the same code to produce completely different behavior in different Assistant instances.
useclient.assistants.create()Create an Assistant, passing in the graph name and initial configuration.
from langgraph_sdk import get_client
client = get_client(url="http://localhost:8123")
# 创建 personal 助手(version 1)
personal_assistant = await client.assistants.create(
"task_maistro", # 已部署的图名称
config={"configurable": {"todo_category": "personal"}}
)
print(personal_assistant["assistant_id"]) # uuid
print(personal_assistant["version"]) # 1
create()The returned object containsassistant_id、version、configand persist to PostgreSQL.
When deploying the diagram, aDefault Assistant(version 1, empty config). If used directlyclient.runs.stream(thread_id, "task_maistro", ...)Instead of passing it onassistant_id, this default Assistant is used.
useclient.assistants.update()Add new configuration to existing Assistant, each call will generate anew version, the old version is automatically retained.
task_maistro_role = """You are a friendly and organized personal task assistant.
- When providing a 'todo summary':
1. List tasks grouped by deadline (overdue, today, this week, future)
2. Highlight tasks missing deadlines
- Proactively ask for deadlines when new tasks lack them
- Tone: encouraging and supportive"""
configurations = {
"todo_category": "personal",
"user_id": "lance",
"task_maistro_role": task_maistro_role,
}
personal_assistant = await client.assistants.update(
personal_assistant["assistant_id"], # 传入已有 ID
config={"configurable": configurations}
)
print(personal_assistant["version"]) # 2
every timeupdate()The old version will not be overwritten, but the new version will be appended. This provides a safety net for experimental configurations - if newtask_maistro_roleIf the effect is not ideal, you can switch back to the historical version at any time.
Typical use case of task_mAIstro: Use two Assistants to manage personal tasks and work tasks respectively, isolated from each other.
todo_category: "personal"
Use an encouraging tone, remind you of deadlines, and focus on life matters (swimming lessons, housework, travel, etc.).
todo_category: "work"
Professional and efficient, recommending reasonable deadlines based on task types (DevRel 1 day, Document Sprint 3 days, etc.).
user_input = "Create another ToDo: Finalize set of report generation tutorials."
thread = await client.threads.create()
async for chunk in client.runs.stream(
thread["thread_id"],
work_assistant_id, # 使用 work assistant 的 ID
input={"messages": [HumanMessage(content=user_input)]},
stream_mode="values"
):
if chunk.event == 'values':
convert_to_messages(chunk.data["messages"])[-1].pretty_print()
# 用户在同一线程回复截止日期
user_input = "OK, for this task let's get it done by next Tuesday."
async for chunk in client.runs.stream(
thread["thread_id"], # 复用同一线程,保持上下文
work_assistant_id,
input={"messages": [HumanMessage(content=user_input)]},
stream_mode="values"
):
if chunk.event == 'values':
convert_to_messages(chunk.data["messages"])[-1].pretty_print()
user_input = "Give me a todo summary."
thread = await client.threads.create()
async for chunk in client.runs.stream(
thread["thread_id"],
personal_assistant_id, # 切换到 personal assistant
input={"messages": [HumanMessage(content=user_input)]},
stream_mode="values"
):
if chunk.event == 'values':
convert_to_messages(chunk.data["messages"])[-1].pretty_print()
The two Assistants, Personal and Work, each use differenttodo_category, so the keys when writing to Store are different, and their respective ToDo lists are completely independent and will not contaminate each other.
All Assistants are persisted in PostgreSQL and can be queried and deleted at any time through the SDK.
assistants = await client.assistants.search()
for assistant in assistants:
print({
'assistant_id': assistant['assistant_id'],
'version': assistant['version'],
'config': assistant['config']
})
# 先创建一个临时 assistant
temp_assistant = await client.assistants.create(
"task_maistro",
config={"configurable": configurations}
)
# 删除它
await client.assistants.delete(temp_assistant["assistant_id"])
# 确认已删除
assistants = await client.assistants.search()
print(len(assistants)) # 回到删除前的数量
Deleting an Assistant will not delete the thread (Thread) and session history associated with it. Threads are stored independently. But after deletingassistant_idInvalid and can no longer be used to create new runs.
# 按返回顺序分配(通常按创建时间倒序)
work_assistant_id = assistants[0]['assistant_id']
personal_assistant_id = assistants[1]['assistant_id']
In a production environment, it is recommended toassistant_idPersistence to the application database instead of retrieving fromsearch()Inferred indexing - ordering may be unstable when multiple people are collaborating.
| Dimensions | Default Assistant | Custom Assistant |
|---|---|---|
| How to create | Automatically generated when deploying diagrams | client.assistants.create() |
| Configuration | Empty config (use graph defaults) | Custom configurable fields |
| Versioning | Fixed version 1 | every timeupdate()incremental version |
| data isolation | All calls share a context | Isolate data by different config keys |
| Applicable scenarios | Development testing, single scenario | Multiple users, multiple business lines, multiple languages, etc. |
when you needThe same set of graph logic serves multiple configurationsUse Assistants when using: multi-tenant SaaS (independent configuration for each customer), separation of roles (customer service vs sales vs technical), A/B testing different system prompts, multi-language assistants (Chinese version vs English version). Assistants eliminate the need to re-deploy code for these scenarios.
6-1 Creating: Package the graph code into a Docker image, and use docker-compose to start three services (LangGraph Server + PostgreSQL + Redis).
6-2 Connecting: Connect to services through LangGraph SDK, manage threads and operations, and achieve streaming output.
6-3 Double Texting:usemultitask_strategyHandle concurrent messages - Reject / Enqueue / Interrupt / Rollback.
6-4 Assistants: Use the same picture, differentconfigurableCreate multiple sets of isolation assistants to support version management.