Skip to content

Agent Management Tools โ€‹

All tools use gnosari_id (not agent_id) as the identifier parameter. They call core services directly โ€” no HTTP proxy to the Gnosari API.

Errors propagate as MCP-level isError: true responses, not as success: false dicts.


gnosari_create โ€‹

Create a new private agent with sensible defaults.

Annotations: readOnlyHint: false ยท destructiveHint: false ยท idempotentHint: false ยท openWorldHint: false

Parameters โ€‹

NameTypeRequiredDescription
namestringYesDisplay name shown in chat and dashboard
instructionsstringYesSystem prompt defining the agent's behavior and goals
descriptionstringNoAgent purpose description for the dashboard

Returns โ€‹

AgentSummaryWithHints:

FieldTypeDescription
agentAgentSummaryReadSummary with gnosari_id, name, access_level, model
hintslist[str]Maximum hints โ€” bare agent needs full configuration

Example โ€‹

python
result = gnosari_create(
    name="Product Support Bot",
    instructions="You help customers with product questions and troubleshooting."
)

gnosari_id = result.agent.gnosari_id
print(result.hints)
# ["Set instructions with gnosari_manage_instructions...",
#  "Make public with gnosari_manage_access...",
#  "Add knowledge with gnosari_manage_knowledge...", ...]

gnosari_get โ€‹

Get a complete overview of an agent's configuration.

Annotations: readOnlyHint: true ยท destructiveHint: false ยท idempotentHint: true ยท openWorldHint: false

Parameters โ€‹

NameTypeRequiredDefaultDescription
gnosari_idintegerYes-ID of the agent to retrieve
include_instructionsbooleanNofalseInclude full instructions text (default false to reduce token cost)

Returns โ€‹

GnosariOverview โ€” organized into logical sections:

SectionFields
Identitygnosari_id, name, description, model, temperature, reasoning_effort
Instructionsinstructions_length, instructions_preview, instructions_version, instructions (if requested)
Accessaccess_level, uri, domain_name, domain_id, public_url
Appearancegreeting, empty_state_title, empty_state_description, suggested_prompts, theme_id, image_url
Knowledgesources (list of KnowledgeSourceSummaryRead)
Traitstraits (list of TraitSummaryRead)
Data Collectiontemplates (list of _DataCollectionItem with id, name, collection_mode)
Collection Summarycollection (CollectionSummaryOut | null) โ€” record_count, new_count, last_capture for this agent (null if no records collected)
Hintshints (empty when fully configured)

Example โ€‹

python
overview = gnosari_get(gnosari_id=123)

print(f"Agent: {overview.name}")
print(f"Access: {overview.access_level}")
print(f"Public URL: {overview.public_url}")
print(f"Knowledge sources: {len(overview.sources)}")
print(f"Instructions preview: {overview.instructions_preview}")

# Get full instructions
overview_full = gnosari_get(gnosari_id=123, include_instructions=True)
print(overview_full.instructions)

gnosari_update โ€‹

Update an agent's identity and model settings. Only modifies provided fields.

For instructions, access, appearance, knowledge, traits, and data collection โ€” use the dedicated tools.

Annotations: readOnlyHint: false ยท destructiveHint: false ยท idempotentHint: false ยท openWorldHint: false

Parameters โ€‹

NameTypeRequiredDescription
gnosari_idintegerYesID of the agent to update
namestringNoNew display name
descriptionstringNoNew purpose description
modelstringNoLLM model (e.g. gpt-5.4-mini, gpt-5.4, claude-sonnet-4); omitted โ†’ the deployment's GNOSARI_DEFAULT_MODEL
temperaturefloatNoCreativity 0.0โ€“2.0
reasoning_effortstringNoDepth: low, medium, high (Claude models only)
clear_fieldslist of stringNoFields to reset to NULL โ€” interactive_buttons_behavior (reverts to the canonical default) or instructions (empties the system prompt; this is the only instructions write that lives here โ€” everything else goes through gnosari_manage_instructions). Passing a field here and as a value param in the same call is rejected

At least one field must be provided. If none are provided, raises ValueError.

Returns โ€‹

AgentSummaryWithHints with hints reflecting current configuration state.

Example โ€‹

python
# Change model and temperature
result = gnosari_update(
    gnosari_id=123,
    model="gpt-5",
    temperature=0.5
)
print(result.agent.model)  # "gpt-5"

gnosari_delete โ€‹

Delete an agent and all its associated data. Two-phase: preview first, confirm second.

Annotations: readOnlyHint: false ยท destructiveHint: true ยท idempotentHint: true ยท openWorldHint: false

Parameters โ€‹

NameTypeRequiredDefaultDescription
gnosari_idintegerYes-ID of the agent to delete
confirmedbooleanNofalseMust be true to delete. When false, returns warning details

Returns โ€‹

  • confirmed=false โ†’ DeleteConfirmationResponse: includes agent name, access level, warning message, and instruction for confirming
  • confirmed=true โ†’ DeletedResponse: {"gnosari_id": 123, "message": "Agent 123 permanently deleted."}

Example โ€‹

python
# Phase 1: Preview
preview = gnosari_delete(gnosari_id=123)
print(preview.warning)
# "Deleting 'Support Bot' will permanently remove the agent,
#  its joina.chat link, collected data, knowledge, traits, and config."

# Phase 2: Confirm (after user approval)
result = gnosari_delete(gnosari_id=123, confirmed=True)
print(result.message)  # "Agent 123 permanently deleted."

gnosari_manage_instructions โ€‹

Update an agent's system instructions โ€” anchored partial edits, or a whole-text replace, append or prepend.

Annotations: readOnlyHint: false ยท destructiveHint: false ยท idempotentHint: false ยท openWorldHint: false

Parameters โ€‹

NameTypeRequiredDefaultDescription
gnosari_idintegerYes-ID of the agent to update
actionstringYes-edit, replace, append, or prepend
contentstringNonullWhole-text payload for replace, append, prepend. Required for those three; never combine with edits
editslist[TextEdit]NonullAnchored partial edits. Required for action="edit", rejected on the other actions. Maximum 20 per call
expected_versionstringNonullThe instructions_version from your last read (or from the previous write's response). If the stored text changed underneath you, the call is refused with CONFLICT and nothing is written
confirm_replacebooleanNofalseDeliberate-overwrite flag. Required when action="replace" would discard more than 2000 stored characters; ignored on every other action
ActionEffect
editApplies the anchored edits in order, all-or-nothing. Everything outside the anchors stays byte-identical. Prefer this for any change to existing text
replaceOverwrites all current instructions
appendAdds content to the end of existing instructions
prependAdds content to the beginning of existing instructions

TextEdit โ€‹

Each entry in edits:

FieldTypeRequiredDescription
opstringYesreplace, insert_before, insert_after, delete, append, or prepend
oldstringFor replace, insert_before, insert_after, deleteExact anchor substring, matched byte-for-byte and whitespace-significant. Must occur exactly once unless replace_all=True; widen it with surrounding lines if it is ambiguous
newstringFor replace, insert_before, insert_after, append, prependThe text to write. No newline is ever added implicitly โ€” write it yourself
replace_allbooleanNo (default false)Apply to every occurrence instead of requiring uniqueness. Valid for replace and delete only

Returns โ€‹

InstructionsResult:

FieldTypeDescription
gnosari_idintAgent ID
instructions_lengthintCharacter count after operation
previewstrFirst 200 characters
action_performedstrWhat was done: replace, append, prepend, or edit
instructions_versionstrContent hash of the instructions after this write (16 lowercase hex), read back from storage. Pass it as the next call's expected_version
appliedlist[AppliedEdit]One entry per anchored edit, in submitted order โ€” index, op, excerpt
readinessReadinessConfiguration completeness: machine-readable missing keys and prioritized next steps

applied is populated for edit (one entry per edit) and for a non-empty append/prepend (one entry). It is empty for replace, which is not an anchored operation, and for an append/prepend with empty content, which is a silent no-op.

excerpt comes from the edit engine, not from this tool: it is the text around the change in the post-edit document. On a short instruction set that window can cover the whole document, so do not assume the excerpt is a small localized snippet.

Example โ€‹

Read the version, edit one anchored span, verify from the response โ€” no second read:

python
overview = gnosari_get(gnosari_id=123, include_instructions=True)
print(overview.instructions_version)  # "db42c544020661e8"

result = gnosari_manage_instructions(
    gnosari_id=123,
    action="edit",
    edits=[
        {
            "op": "replace",
            "old": "Always answer in English.",
            "new": "Always answer in the language the visitor used.",
        },
        {
            "op": "insert_after",
            "old": "## Escalation",
            "new": "\nHand off to a human after two failed attempts.",
        },
    ],
    expected_version=overview.instructions_version,
)

print(result.action_performed)       # "edit"
print(result.instructions_version)   # "c99c55daf9809044" โ€” use this next time
for entry in result.applied:
    print(entry.index, entry.op, entry.excerpt)

Whole-text actions still work unchanged:

python
# Write a brand new instruction set
gnosari_manage_instructions(
    gnosari_id=123,
    action="replace",
    content="You are a helpful customer support agent for Acme Corp...",
)

# Add a rule at the end
gnosari_manage_instructions(
    gnosari_id=123,
    action="append",
    content="\n\nAlways end responses with: 'Is there anything else I can help you with?'",
)

Refusals โ€‹

Refusals raise (isError: true) and write nothing. The message carries the code, the failing edit index when there is one, and every detail key:

CONFLICT: the text changed since it was read; re-read it and retry
  current_version: c99c55daf9809044
  current_length: 207
CodeCauseFix
VALIDATION_ERRORcontent and edits combined; edits missing or empty on action="edit"; content missing; an edit whose old equals its new; more than 20 edits; empty content on action="replace"; an over-threshold replace without confirm_replaceFollow the redirect in the message โ€” every problem found is named in one refusal
ANCHOR_NOT_FOUNDold does not occur in the stored textRe-read the instructions and copy the anchor exactly, whitespace included
ANCHOR_AMBIGUOUSold matched more than once and replace_all=FalseWiden old with surrounding lines (the message lists match_count and one excerpt per match), or set replace_all=True
CONFLICTexpected_version does not match the stored hashRe-read, re-anchor against the current text, retry with the current_version from the message

Two refusals are specific to action="replace":

  • Over-threshold overwrite. Replacing more than 2000 stored characters โ€” the text that would be discarded, never the size of the incoming payload โ€” requires confirm_replace=True. Prefer action="edit" instead of confirming.
  • Empty content. content="" on action="replace" is refused: it does not clear instructions. To clear them, call gnosari_update(gnosari_id=123, clear_fields=["instructions"]). append/prepend with empty content are not refused โ€” they are a no-op with applied=[].

gnosari_manage_access โ€‹

Configure an agent's access level and public URL.

Annotations: readOnlyHint: false ยท destructiveHint: false ยท idempotentHint: false ยท openWorldHint: false

Parameters โ€‹

NameTypeRequiredDescription
gnosari_idintegerYesID of the agent to update
access_levelstringYesPUBLIC, PRIVATE, or PASSWORD_PROTECTED
uristringNoURL path for joina.chat/{uri}. Required for PUBLIC/PASSWORD_PROTECTED
domainstringNoDomain name to publish on (resolved to domain_id)
domain_idintegerNoDomain ID (takes precedence over domain if both provided)
passwordstringNoPassword for PASSWORD_PROTECTED access (min 8 chars)
Access LevelWho can access
PUBLICAnyone with the joina.chat link
PASSWORD_PROTECTEDAnyone with the link + password
PRIVATEAPI/embed access only (no public URL)

Returns โ€‹

AgentSummaryWithHints. The agent.public_url field is populated when access level is PUBLIC or PASSWORD_PROTECTED.

Examples โ€‹

python
# Make agent public
result = gnosari_manage_access(
    gnosari_id=123,
    access_level="PUBLIC",
    uri="support-bot"
)
print(result.agent.public_url)  # "https://joina.chat/acme/support-bot"

# Password-protected
gnosari_manage_access(
    gnosari_id=123,
    access_level="PASSWORD_PROTECTED",
    uri="internal-bot",
    password="secret2024"
)

# Revert to private
gnosari_manage_access(gnosari_id=123, access_level="PRIVATE")

gnosari_manage_appearance โ€‹

Configure an agent's visual appearance and welcome experience. This is the primary surface for theming a chat โ€” the schema alone is enough to apply a complete visual identity.

Annotations: readOnlyHint: false ยท destructiveHint: false ยท idempotentHint: false ยท openWorldHint: false

At least one field must be provided.

The two config layers โ€‹

Chat appearance resolves from two layers:

LayerWhere it livesWhat it holdsSet via
1. Agent chat UI (CONTENT)Agent.configuration.chat_uiPer-agent greeting, empty-state, suggested prompts.greeting, empty_state_*, suggested_prompts
2. Chat theme (VISUAL identity)chat_theme.configuration (canonical v2)Reusable branding โ€” color preset + background pattern. Branding is theme-only โ€” agents never override it per chat.style_preset

Visual identity is chosen with ONE curated style_preset (see below). The preset resolves to a color preset + background pattern and is written to the agent's chat theme. Theme writes reuse the agent's existing theme in place (one row) โ€” repeated calls never create duplicate theme rows.

Parameters โ€‹

NameTypeRequiredDescription
gnosari_idintegerYesID of the agent to update
greetingstringNoFirst message shown when a user opens a new chat (layer 1)
empty_state_titlestringNoLarge title text for the welcome screen (layer 1)
empty_state_descriptionstringNoSupporting text below the welcome title (layer 1)
suggested_promptslist[SuggestedPromptInput]NoClickable prompt buttons (max 8). Replaces all existing (layer 1)
style_presetstring (enum)NoONE curated visual identity โ€” color preset + background pattern (layer 2). One of the 12 values below
image_urlstringNoAgent avatar/logo URL (max 500 chars, publicly accessible)

SuggestedPromptInput format:

python
{"title": "Button label", "prompt": "Full prompt text sent on click"}

style_preset โ€‹

A style_preset is a single curated combo that covers BOTH the color palette and the background pattern โ€” pick one by the agent's purpose/brand. It is a type-locked enum: only the 12 values below are accepted, and there is no raw-hex or font input from this tool. Applying a preset writes (or updates in place) the agent's chat theme and echoes the applied id back in the result.

style_presetColorPatternUse it for
plainskynoneNo pattern, clean sky accent. Corporate/formal, or let content lead.
clean-dotsskyfine-dotsMinimal sky-blue, faint dots. SaaS, B2B, dashboards.
ocean-wavesoceanwavesCalm blue, flowing waves. Wellness, travel, spa, relaxed brands.
forest-topoforesttopographyGreen, contour lines. Outdoors, sustainability, nature, eco.
blueprintblueblueprintTechnical blue grid. Engineering, dev tools, architecture.
graph-paperindigograph-paperIndigo grid. Education, finance, data, analytical tone.
circuittealcircuitTeal circuit lines. Tech, hardware, AI, electronics.
soft-bubblesrosebubblesWarm rose, soft bubbles. Friendly, lifestyle, community, care.
sunset-glowsunsetorganic-blobsVibrant sunset, organic blobs. Creative, marketing, bold consumer.
emerald-gridemeraldsubtle-gridFresh emerald, subtle grid. Health, growth, productivity.
confettifuchsiaconfettiEnergetic fuchsia, confetti. Events, kids, playful/fun brands.
mono-noisevioletnoiseEditorial violet, subtle grain. Media, publishing, premium/minimal.

Returns โ€‹

AppearanceResult:

FieldTypeDescription
gnosari_idintAgent ID
greetingstrCurrent greeting
empty_state_titlestrCurrent title
empty_state_descriptionstrCurrent description
suggested_prompts_countintNumber of prompts configured
chat_theme_idint | nullCurrent theme ID (the DB row id; echoed so you can confirm the in-place reuse)
style_presetstr | nullThe style_preset id applied on this call (echoed back), or null if none
image_urlstrCurrent avatar URL
notestrAdvisory note (e.g. greeting hides the welcome screen)
readinessReadinessConfiguration completeness with missing keys and next steps

Examples โ€‹

Welcome content + a curated visual identity:

python
result = gnosari_manage_appearance(
    gnosari_id=123,
    greeting="Hi! How can I help you today?",
    empty_state_title="Acme Support",
    empty_state_description="Ask questions about our products and services.",
    suggested_prompts=[
        {"title": "What's included?", "prompt": "What's included in the Pro plan?"},
        {"title": "How do I get started?", "prompt": "Walk me through getting started"}
    ],
    style_preset="clean-dots",
    image_url="https://example.com/avatar.png"
)
print(f"Prompts configured: {result.suggested_prompts_count}")
print(f"Style preset applied: {result.style_preset}")

Change just the visual identity (reuses the agent's theme row in place):

python
result = gnosari_manage_appearance(
    gnosari_id=123,
    style_preset="ocean-waves",
)
print(f"Theme assigned: {result.chat_theme_id} โ€” preset {result.style_preset}")

gnosari_health_check โ€‹

Health check for monitoring server status.

Annotations: readOnlyHint: true ยท destructiveHint: false ยท idempotentHint: true ยท openWorldHint: false

No parameters. No authentication required.

Returns โ€‹

python
{
    "status": "healthy",
    "server": "gnosari-mcp",
    "version": "x.x.x",
    "api_url": "http://gnosari-api.localhost"
}

Example โ€‹

python
health = gnosari_health_check()
print(health["status"])   # "healthy"
print(health["version"])  # "2.1.0"

Common Errors โ€‹

ErrorCauseSolution
AgentNotFoundErrorgnosari_id does not existVerify ID with gnosari_search
AgentAccessDeniedErrorAgent belongs to a different accountConfirm the ID belongs to your account
AgentValidationErrorURI already taken on the domainCheck with gnosari_check_uri first
ValueError (no update fields)Called gnosari_update with no fieldsProvide at least one field to update
ValueError (no appearance fields)Called gnosari_manage_appearance with no fieldsProvide at least one appearance field

Next Steps โ€‹