Skip to content

Agent Creation Guide ​

Complete walkthrough for creating AI agents with the Gnosari MCP Server. Uses the gnosari_* atomic decomposition pattern — one tool per configuration concern.


Overview ​

Creating an agent is a multi-step process:

  1. gnosari_create — bare agent with name and instructions
  2. gnosari_manage_knowledge — add domain expertise (optional)
  3. gnosari_manage_traits — personality traits (optional)
  4. gnosari_manage_appearance — welcome experience (optional)
  5. gnosari_manage_data_collection — structured data extraction (optional)
  6. gnosari_manage_access — publish to joina.chat

Each step is independent. The hints field in every response guides what to configure next.


Pattern 1: Simple Private Agent ​

Create a chatbot for internal use — stays PRIVATE, no publishing needed.

python
result = gnosari_create(
    name="Internal FAQ Bot",
    instructions="""You are a helpful internal assistant for Acme Corp employees.

Answer questions about:
- Company policies (use /wiki/policies for reference)
- Benefits and HR topics
- IT support procedures

Direct escalations to hr@acme.com (HR) or it@acme.com (IT)."""
)

gnosari_id = result.agent.gnosari_id
print(f"Created agent: {gnosari_id}")
# Agent is immediately usable via API or embed widget

Verify:

python
overview = gnosari_get(gnosari_id=gnosari_id)
print(f"Name: {overview.name}")
print(f"Access: {overview.access_level}")  # "PRIVATE"
print(f"Instructions: {overview.instructions_length} chars")

Pattern 2: Public Knowledge Assistant ​

Create a public agent that answers questions using external documentation.

Step 1: Create the agent ​

python
result = gnosari_create(
    name="Product Documentation Assistant",
    instructions="""You are a helpful documentation assistant for Acme products.

Guidelines:
- Base answers on the provided documentation
- If something isn't in the docs, say so clearly
- Provide specific references when possible
- Be accurate and concise"""
)
gnosari_id = result.agent.gnosari_id

Step 2: Add knowledge ​

python
# Recommended default — omit `type` entirely. The server probes for a
# sitemap first, then falls back to crawl-based discovery automatically.
gnosari_manage_knowledge(
    action="create",
    name="Product Documentation",
    url="https://docs.acme.com",
    gnosari_id=gnosari_id
)

If you want to ingest a single page instead of the whole site, pass single_page=true. To force a specific loader, pass type explicitly:

python
# Opt out of whole-site ingestion — load only this one page
gnosari_manage_knowledge(
    action="create",
    name="FAQ",
    url="https://acme.com/faq",
    single_page=True,
    gnosari_id=gnosari_id
)
InputWhen to use
omitted or type="website"Recommended default — auto-resolves sitemap if one exists, else discovery
single_page=trueLoad ONLY the given URL as a single page (stored data_type="website"), no probe
type="sitemap"Force sitemap ingestion even if auto-resolve would pick differently
type="discovery"Force crawl-based discovery even if a sitemap exists

Step 3: Set appearance ​

python
gnosari_manage_appearance(
    gnosari_id=gnosari_id,
    greeting="Hi! I can help you understand Acme products. What would you like to know?",
    style_preset="clean-dots"
)

Step 4: Publish ​

python
# Check URI first
check = gnosari_check_uri(uri="product-docs")
if check.available:
    gnosari_manage_access(
        gnosari_id=gnosari_id,
        access_level="PUBLIC",
        uri="product-docs"
    )
    print(f"Live at: https://joina.chat/acme/product-docs")

Monitor knowledge loading ​

python
overview = gnosari_get(gnosari_id=gnosari_id)
for source in overview.sources:
    print(f"{source.name}: {source.loading_status}")
    # loading_status: unloaded | loading | loaded | failed

Pattern 3: Lead Collection Agent ​

Create a public agent that collects contact information from visitors.

python
# Create
result = gnosari_create(
    name="Sales Lead Qualifier",
    instructions="""You are a sales assistant that helps qualify leads for Acme.

Your goals:
1. Understand the visitor's needs and use case
2. Naturally collect their contact information
3. Assess fit for Acme products

Be conversational — don't feel like a form."""
)
gnosari_id = result.agent.gnosari_id

# Model tuning for natural conversation
gnosari_update(gnosari_id=gnosari_id, model="gpt-5", temperature=0.8)

# Data collection — active mode proactively asks for info
gnosari_manage_data_collection(
    action="create",
    name="Lead Qualification",
    description="Capture lead details for sales follow-up",
    fields=[
        {
            "name": "full_name",
            "field_type": "text",
            "description": "Person's full name",
            "required": True
        },
        {
            "name": "email",
            "field_type": "email",
            "description": "Contact email address",
            "required": True
        },
        {
            "name": "company",
            "field_type": "text",
            "description": "Company or organization name",
            "required": False
        },
        {
            "name": "use_case",
            "field_type": "text",
            "description": "What they want to use Acme for",
            "required": False
        }
    ],
    gnosari_id=gnosari_id,
    collection_mode="active"  # proactively ask
)

# Publish
gnosari_manage_access(gnosari_id=gnosari_id, access_level="PUBLIC", uri="sales")

Collection modes:

ModeBehaviorBest for
passiveExtract silently, never askBackground enrichment
opportunisticCapture when mentioned + brief follow-upsNatural collection
activeProactively ask for required fieldsLead forms, intake
guidedFollow a custom scriptStructured workflows

Knowledge + traits + appearance + data collection + publish.

python
# 1. Create
result = gnosari_create(
    name="Enterprise Support Agent",
    instructions="""You are an enterprise support specialist for Acme platform.

Responsibilities:
- Answer technical questions using the knowledge base
- Troubleshoot common issues step by step
- Collect support ticket information when needed
- Escalate critical issues to on-call: +1-555-ACME

Tone: professional, patient, technically precise."""
)
gnosari_id = result.agent.gnosari_id

# 2. Knowledge
gnosari_manage_knowledge(
    action="create", name="Technical Docs",
    url="https://docs.acme.com/sitemap.xml", type="sitemap",
    gnosari_id=gnosari_id
)
gnosari_manage_knowledge(
    action="create", name="Troubleshooting Guide",
    url="https://help.acme.com", type="website",
    gnosari_id=gnosari_id
)

# 3. Traits — find then assign
traits = gnosari_manage_traits(action="list")
professional_id = next(t.id for t in traits.data if "professional" in t.name.lower())
empathetic_id = next(t.id for t in traits.data if "empathetic" in t.name.lower())
gnosari_manage_traits(
    action="assign",
    trait_ids=[professional_id, empathetic_id],
    gnosari_id=gnosari_id
)

# 4. Appearance
gnosari_manage_appearance(
    gnosari_id=gnosari_id,
    greeting="Hi! I'm here to help with technical questions and support. How can I assist you today?",
    empty_state_title="Enterprise Support",
    empty_state_description="Get help with technical issues, billing, and account management.",
    suggested_prompts=[
        {"title": "Technical issue", "prompt": "I'm having a technical problem, can you help?"},
        {"title": "Billing question", "prompt": "I have a question about my invoice"}
    ],
    style_preset="blueprint",
    image_url="https://acme.com/support-avatar.png"
)

# 5. Data collection
gnosari_manage_data_collection(
    action="create",
    name="Support Ticket",
    description="Track issue details for resolution",
    fields=[
        {"name": "issue_type", "field_type": "text", "description": "Category: login, billing, technical, feature", "required": True},
        {"name": "priority", "field_type": "text", "description": "Priority: low, medium, high, critical", "required": True},
        {"name": "error_message", "field_type": "text", "description": "Any error messages seen", "required": False}
    ],
    gnosari_id=gnosari_id,
    collection_mode="opportunistic"
)

# 6. Publish
gnosari_manage_access(gnosari_id=gnosari_id, access_level="PUBLIC", uri="support")

# 7. Verify (hints empty = fully configured)
overview = gnosari_get(gnosari_id=gnosari_id)
print(f"Public URL: {overview.public_url}")
print(f"Knowledge: {len(overview.sources)} sources")
print(f"Hints: {overview.hints}")  # []

Updating an Existing Agent ​

Update instructions ​

python
gnosari_manage_instructions(
    gnosari_id=456,
    action="replace",
    content="New system prompt..."
)

# Add a rule at the end
gnosari_manage_instructions(
    gnosari_id=456,
    action="append",
    content="\n\nNEW: 24/7 support now available for enterprise customers."
)

Add a knowledge source ​

python
gnosari_manage_knowledge(
    action="create",
    name="API Reference",
    url="https://api.acme.com/docs",
    type="sitemap",
    gnosari_id=456
)

Remove a knowledge source ​

python
# List sources to find the ID
result = gnosari_manage_knowledge(action="list")
old_source = next(s for s in result.data if s.name == "Old Docs")

# Remove from agent
gnosari_manage_knowledge(action="remove", source_ids=[old_source.id], gnosari_id=456)

# Optionally delete the source entirely
gnosari_manage_knowledge(action="delete", source_id=old_source.id)

Change model ​

python
gnosari_update(gnosari_id=456, model="gpt-5", temperature=0.5)

Monitor Collected Data ​

After creating an agent with data collection, view what it's capturing:

python
# Stats overview
stats = get_collection_stats(agent_id=gnosari_id, days=7)
print(f"Total collected: {stats.total}")
for status, count in stats.status_counts.items():
    print(f"  {status}: {count}")

# Individual records
records = list_collected_data(agent_id=gnosari_id, status="new", days=1)
print(f"New today: {records.pagination.total}")
for entry in records.data:
    print(f"{entry.template_name}: {entry.attributes_summary}")

Troubleshooting ​

Agent not created ​

Error: VALIDATION_ERROR or ValueError

Cause: Missing required field

Fix: name and instructions are required for gnosari_create

python
gnosari_create(name="Bot", instructions="Test agent")

URI conflict ​

Error: AgentValidationError

Cause: URI already taken on the domain

Fix: Check availability first

python
check = gnosari_check_uri(uri="my-bot")
print(check.available)   # False
print(check.hints)       # ["Try 'my-bot-2' or 'my-bot-bot'"]

Knowledge source failed ​

Symptom: loading_status: "failed" in gnosari_get

Cause: URL inaccessible, no content, or crawl timeout

Fix:

  1. Verify the URL is publicly accessible
  2. For sitemap: verify sitemap.xml exists and returns valid XML
  3. Delete and recreate the source
python
gnosari_manage_knowledge(action="delete", source_id=45)
gnosari_manage_knowledge(
    action="create",
    name="Docs (retry)",
    url="https://docs.acme.com/sitemap.xml",
    type="sitemap",
    gnosari_id=gnosari_id
)

Auth failed ​

Error: AUTHENTICATION_FAILED

Cause: Invalid or missing API key

Fix: Check the Gnosari-Api-Key header value

bash
# Test authentication
curl -H "Gnosari-Api-Key: $GNOSARI_API_KEY" http://gnosari-mcp.localhost/

Next Steps ​