Skip to content

Migration Guide ​


What changed: AgentLink absorbed QrLink. The tool was renamed and extended: every link now opens an agent as a classic chat OR an immersive full-page conversation, with per-link greeting/topic/theme/expiry overrides. gnosari_manage_qr is deleted outright — no alias. Tool count is unchanged (16 → 16); this is a rename + extension, not a consolidation.

Why: QR links were a single narrow use case (physical media redirects). Conversation Mode generalizes the same entity into a general-purpose shareable link — a QR code is now one derived artifact of every link, not the whole feature.

Breaking changes ​

ChangeMigration
gnosari_manage_qr removedUse gnosari_manage_link. Same actions: create, get, list, update, delete, check_slug
qr_link_id param → link_idRename the parameter in every call
clear_agent: bool → clear_fields: list[str]clear_agent=True has no direct replacement (a link always needs an agent — re-point it with a new agent_id instead). clear_fields now resets greeting / topic / chat_theme_id / expires_at back to inherit
scan_count field → visit_countRead visit_count instead
Return shape QrLinkRead → LinkDetailAdds presentation, greeting, topic, expires_at, and a urls object (public, embed, qr_image) in place of a bare slug
New: presentation, greeting, topic, chat_theme_id, expires_at paramsOptional on create/update. Default presentation is chat (identical behavior to the old QR link)

Migration pattern ​

python
# Old way — gnosari_manage_qr
qr = gnosari_manage_qr(action="create", name="Card QR", slug="card", agent_id=123)
print(f"joina.chat/q/{qr['slug']}")
gnosari_manage_qr(action="update", qr_link_id=qr["id"], clear_agent=True)

# New way — gnosari_manage_link (same default behavior, presentation="chat")
link = gnosari_manage_link(action="create", name="Card QR", slug="card", agent_id=123)
print(link.urls.public)  # joina.chat/l/card
gnosari_manage_link(action="update", link_id=link.id, agent_id=456)  # re-point instead of clearing

# New capability — immersive conversation presentation, not possible before
gnosari_manage_link(
    action="update", link_id=link.id, presentation="conversation", topic="A conversation about your stay"
)

Printed QR codes encoding the old joina.chat/q/{slug} keep working — the API retains a legacy /resolve/qr/{slug} alias so existing physical media never needs reprinting.


v5: 17 tools → 16 tools — Tool UX v2 ​

What changed: gnosari_create became a validate-first atomic composite, prose hints became a structured readiness block, and the domain surface was removed.

Why: Agents walked into dead ends — schemas advertised things that could not succeed, defaults contradicted the product, and post-create guidance was prose hints agents ignored.

Breaking changes ​

ChangeMigration
gnosari_create requires empty_state_title, empty_state_description, data_collectionAdd these to every create call. The result is a live-ready intake agent in one call (welcome + data collection). Optional greeting, suggested_prompts, publish, uri
gnosari_list_domains removedDrop it. Publishing resolves the default domain (joina.chat) server-side
domain / domain_id params removed from gnosari_manage_access, gnosari_check_uri, gnosari_searchDrop the params. Default domain is resolved server-side
gnosari_embed_code param agent_id: str → gnosari_id: intPass the integer agent id
collection_mode default passive → activeSet mode/collection_mode explicitly if you relied on the old passive default
Prose hints → readiness blockRead readiness.percent / readiness.missing / readiness.next_steps instead of hints. gnosari_check_uri still returns hints (URI suggestions)

v4: 22 tools → 17 tools — Plan 2 consolidation ​

What changed: Consolidated 10 legacy tools into action-discriminated gnosari_* tools. Renamed 1 tool for consistency.

Why: 5 QR tools and 3 data tools were individually registered — unnecessary API sprawl. Consolidating into gnosari_manage_qr and gnosari_collected_data follows the same manage pattern used by traits, knowledge, and data collection. Also renamed list_domains and gnosari_health_check for namespace consistency.

Tool mapping ​

Old ToolNew ToolNotes
create_qr_linkgnosari_manage_qr(action="create")Same params: name, slug, agent_id
get_qr_linkgnosari_manage_qr(action="get")qr_link_id required
list_qr_linksgnosari_manage_qr(action="list")Same skip/limit pagination
update_qr_linkgnosari_manage_qr(action="update")Added clear_agent bool to detach agent
delete_qr_linkgnosari_manage_qr(action="delete")qr_link_id required
list_collected_datagnosari_collected_data(action="list")Same filters: agent_id, template_name, days, status, search
get_collection_statsgnosari_collected_data(action="stats")Same params: agent_id, days, group_by_agent
list_templatesRemovedUse gnosari_manage_data_collection(action="list") or gnosari_search(entity="templates")
get_embed_codegnosari_embed_codeRenamed for gnosari_* namespace consistency
gnosari_health_checkgnosari_healthShortened name
list_domainsgnosari_list_domainsRenamed for gnosari_* namespace consistency

New feature: clear_agent ​

gnosari_manage_qr(action="update") adds a clear_agent boolean flag that was not possible with the old update_qr_link. This allows detaching an agent from a QR link without deleting the link:

python
# Old: no way to detach agent without setting agent_id=None (which was filtered out)
# New: explicit flag
gnosari_manage_qr(action="update", qr_link_id=1, clear_agent=True)

clear_agent and agent_id are mutually exclusive.

Migration pattern ​

python
# Old way — 5 separate QR tools
qr = create_qr_link(name="Card QR", slug="card", agent_id=123)
links = list_qr_links()
link = get_qr_link(qr_link_id=1)
update_qr_link(qr_link_id=1, agent_id=456)
delete_qr_link(qr_link_id=1)

# New way — single tool
qr = gnosari_manage_qr(action="create", name="Card QR", slug="card", agent_id=123)
links = gnosari_manage_qr(action="list")
link = gnosari_manage_qr(action="get", qr_link_id=1)
gnosari_manage_qr(action="update", qr_link_id=1, agent_id=456)
gnosari_manage_qr(action="delete", qr_link_id=1)

# Old way — 2 data tools
records = list_collected_data(agent_id=123, days=7)
stats = get_collection_stats(agent_id=123, days=30)

# New way — single tool
records = gnosari_collected_data(action="list", agent_id=123, days=7)
stats = gnosari_collected_data(action="stats", agent_id=123, days=30)

# Old way — other renames
code = get_embed_code(agent_id="abc")
health = gnosari_health_check()
domains = list_domains()

# New way
code = gnosari_embed_code(agent_id="abc")
health = gnosari_health()
domains = gnosari_list_domains()

v3: 19 tools → gnosari_* tools ​

What changed: Monolithic create_agent(26 params) replaced by atomic decomposition — one tool per configuration concern.

Why: Single-call creation was all-or-nothing. Atomic tools let you build agents incrementally, retry individual steps, and follow hints to the next configuration step.

Tool mapping ​

Old ToolNew ToolNotes
create_agentgnosari_create + config toolsDecomposed: create bare agent, then configure
get_agentgnosari_getReturns GnosariOverview with hints
update_agent (identity/model)gnosari_updateName, description, model, temperature
update_agent (instructions)gnosari_manage_instructionsReplace, append, or prepend
update_agent (access)gnosari_manage_accessAccess level, URI, domain
update_agent (appearance)gnosari_manage_appearanceGreeting, prompts, theme, image
update_agent (knowledge)gnosari_manage_knowledgeAssign/remove knowledge sources. type is now optional — omit it to auto-resolve sitemap/discovery (see the Manage Resources reference)
update_agent (traits)gnosari_manage_traitsAssign/remove traits
update_agent (data collection)gnosari_manage_data_collectionAssign/remove templates
delete_agentgnosari_deleteTwo-phase with confirmed flag
list_agentsgnosari_search(entity="agents")Text search + filters
list_traitsgnosari_manage_traits(action="list")Or gnosari_search(entity="traits")
list_knowledge_sourcesgnosari_manage_knowledge(action="list")Or gnosari_search(entity="knowledge")

Parameter name change ​

All gnosari_* tools use gnosari_id — not agent_id:

python
# Old
get_agent(agent_id=123)
delete_agent(agent_id=123)

# New
gnosari_get(gnosari_id=123)
gnosari_delete(gnosari_id=123)

Migration pattern ​

python
# Old way — one call, all-or-nothing
result = create_agent(
    name="Support Bot",
    instructions="...",
    access_level="PUBLIC",
    uri="support",
    knowledge_sources=[{"name": "Docs", "url": "https://docs.example.com", "type": "sitemap"}],
    trait_ids=[1, 3],
    chat_theme={"preset": "standard", "greeting": "Hi!"},
    data_collection={"template_name": "Ticket", "fields": [...], "collection_mode": "active"}
)

# New way — atomic decomposition
result = gnosari_create(name="Support Bot", instructions="...")
gnosari_id = result.agent.gnosari_id

gnosari_manage_knowledge(action="create", name="Docs", url="https://docs.example.com", type="sitemap", gnosari_id=gnosari_id)
gnosari_manage_traits(action="assign", trait_ids=[1, 3], gnosari_id=gnosari_id)
gnosari_manage_appearance(gnosari_id=gnosari_id, greeting="Hi!", style_preset="clean-dots")
gnosari_manage_data_collection(action="create", name="Ticket", fields=[...], gnosari_id=gnosari_id, collection_mode="active")
gnosari_manage_access(gnosari_id=gnosari_id, access_level="PUBLIC", uri="support")

v2: 127 tools → 19 tools (legacy reference) ​

What changed: 127 type-specific agent tools replaced by 5 unified tools + 7 resources.

Impact: 85% reduction in tool count (127 → 19), single-call agent creation.

Architecture ​

Before (127 tools)After (19 tools + 7 resources)
create_marketing_agentcreate_agent (no type needed)
create_development_agentcreate_agent
create_content_agentcreate_agent
get_marketing_agent(id)get_agent(agent_id=id)
update_marketing_agent(id, ...)update_agent(agent_id=id, ...)
delete_*_agent(id)delete_agent(agent_id=id)
create_knowledge_source(...) then create_agent(source_id=...)create_agent(knowledge_sources=[{...}]) inline
list_domains() (tool)read_resource("gnosari://domains")
get_traits()read_resource("gnosari://traits")
create_team(...)Use agent instructions instead

Old workflow vs new ​

python
# Before: 8+ sequential calls
domain = get_default_domain()
source = create_knowledge_source(name="Docs", url="...", type="sitemap")
theme = create_chat_theme(preset="standard")
template = create_data_template(name="Lead", fields=[...])
trait = get_trait_by_name("Friendly")
agent = create_marketing_agent(
    name="Bot", instructions="...", domain_id=domain.id,
    knowledge_source_ids=[source.id], chat_theme_id=theme.id,
    data_template_id=template.id, trait_ids=[trait.id], access_level="PUBLIC"
)

# After: 1 call
agent = create_agent(
    name="Bot", instructions="...", access_level="PUBLIC",
    knowledge_sources=[{"name": "Docs", "url": "...", "type": "sitemap"}],
    chat_theme={"preset": "standard"},
    data_collection={"template_name": "Lead", "fields": [...], "collection_mode": "active"},
    trait_ids=[friendly["id"]]
)

Breaking changes ​

ChangeOldNew
No agent type parametercreate_marketing_agent(...)create_agent(...)
Inline resource creationsource_id = create_knowledge_source(...) then pass IDPass config inline in create_agent
Resources replace list toolsdomains = list_domains()domains = read_resource("gnosari://domains")
Team tools removedcreate_team(...)Define team behavior in instructions
Unified get/update/deleteget_marketing_agent(id)get_agent(agent_id=id)

Getting Help ​