Skip to content

Agent Creation Flow

The gnosari_* tools use atomic decomposition — instead of one monolithic call with 20+ parameters, each configuration concern is handled by a dedicated tool.


Philosophy

Before (19-tool era):

python
# One massive call, all-or-nothing
create_agent(
    name="...", instructions="...", model="...", temperature=0.7,
    access_level="PUBLIC", uri="...", domain_id=1,
    knowledge_sources=[...], trait_ids=[...],
    chat_theme={...}, data_collection={...},
    empty_state_title="...", image_url="..."
)

Now (gnosari_ tools):*

python
# Each concern has its own tool
gnosari_create(name="...", instructions="...")          # identity
gnosari_manage_instructions(action="replace", ...)     # instructions
gnosari_manage_knowledge(action="create", ...)         # knowledge
gnosari_manage_traits(action="assign", ...)            # personality
gnosari_manage_appearance(greeting="...", ...)         # visuals
gnosari_manage_access(access_level="PUBLIC", ...)      # publishing

Benefits:

  • Each step is independently verifiable
  • Partial failures don't cascade
  • Retry individual steps without redoing everything
  • Hints guide the next step after each call

Step 1: Create the Bare Agent

Call gnosari_create with name and instructions. The agent starts PRIVATE.

python
result = gnosari_create(
    name="Product Support Bot",
    instructions="You are a helpful support agent for Acme Corp products."
)

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

What happens:

  • Agent record written to PostgreSQL via core/services/agent_service.create_agent()
  • Defaults applied: model = GNOSARI_DEFAULT_MODEL, temperature = 0.7, reasoning_effort = "medium", access_level = PRIVATE
  • Maximum hints returned (bare agent needs full configuration)

Step 2: Refine Instructions (optional)

If you need to build instructions iteratively:

python
# Start with a draft
gnosari_create(name="Bot", instructions="Draft: support agent.")

# Replace with final version
gnosari_manage_instructions(
    gnosari_id=gnosari_id,
    action="replace",
    content="""You are a helpful customer support agent for Acme Corp.

Responsibilities:
- Answer product questions accurately
- Escalate billing issues to support@acme.com
- Never make promises about refunds without checking policy

Tone: professional, patient, clear."""
)

# Append a rule later
gnosari_manage_instructions(
    gnosari_id=gnosari_id,
    action="append",
    content="\n\nAlways confirm the user's issue is resolved before ending the conversation."
)

Step 3: Add Knowledge

Use gnosari_manage_knowledge to add domain expertise. type is optional — omit it to auto-resolve sitemap vs. discovery from the URL (see the Manage Resources reference).

python
# Create a source and assign it in one call — type omitted, auto-resolves
gnosari_manage_knowledge(
    action="create",
    name="Product Documentation",
    url="https://docs.acme.com",
    gnosari_id=gnosari_id  # assign immediately
)

# Or create separately, then assign
gnosari_manage_knowledge(
    action="create",
    name="FAQ",
    url="https://acme.com/faq",
    type="website"
)
# returns KnowledgeSourceRead with id=45

gnosari_manage_knowledge(
    action="assign",
    source_ids=[45],
    gnosari_id=gnosari_id
)

What happens:

  • core/services/knowledge_service.create_source() creates the record
  • Background crawler starts indexing (async)
  • Agent can be used immediately; knowledge becomes available as indexing completes

Loading states: unloadedloadingloaded (or failed)


Step 4: Add Traits (optional)

Traits shape how the agent communicates:

python
# List available traits
traits_result = gnosari_manage_traits(action="list")

# Find trait IDs
friendly_id = next(t.id for t in traits_result.data if t.name == "Friendly")
professional_id = next(t.id for t in traits_result.data if t.name == "Professional")

# Assign
gnosari_manage_traits(
    action="assign",
    trait_ids=[friendly_id, professional_id],
    gnosari_id=gnosari_id
)

Step 5: Configure Appearance (optional)

python
gnosari_manage_appearance(
    gnosari_id=gnosari_id,
    greeting="Hi! I'm here to help with Acme products. What can I assist you with?",
    empty_state_title="Acme Product Support",
    empty_state_description="Get answers to product questions and troubleshooting help.",
    suggested_prompts=[
        {"title": "How do I get started?", "prompt": "Walk me through getting started with Acme"},
        {"title": "Troubleshooting", "prompt": "I'm having an issue, can you help troubleshoot?"}
    ],
    style_preset="clean-dots"
)

Step 6: Configure Data Collection (optional)

python
# Create a template and assign it
gnosari_manage_data_collection(
    action="create",
    name="Support Ticket",
    description="Capture issue details for support tracking",
    fields=[
        {
            "name": "issue_type",
            "field_type": "text",
            "description": "Category: billing, technical, account, other",
            "required": True
        },
        {
            "name": "severity",
            "field_type": "text",
            "description": "Impact level: low, medium, high, critical",
            "required": False
        }
    ],
    gnosari_id=gnosari_id,          # assign immediately
    collection_mode="opportunistic"  # capture naturally during conversation
)

Collection modes:

ModeBehavior
passiveExtract silently, never ask
opportunisticCapture when mentioned + brief follow-ups
activeProactively ask for required fields
guidedFollow a custom_prompt script

Step 7: Publish

Check URI availability, then publish:

python
# Check before committing
check = gnosari_check_uri(uri="product-support")
if not check.available:
    print(f"Taken by: {check.current_gnosari_name}")
    print(check.hints)  # alternatives suggested
    # Try a variation
    check = gnosari_check_uri(uri="product-support-bot")

# Publish
gnosari_manage_access(
    gnosari_id=gnosari_id,
    access_level="PUBLIC",
    uri="product-support"
)

What happens:

  • access_level is updated to PUBLIC
  • Public URL generated: https://joina.chat/{domain-slug}/product-support
  • joina.chat link becomes active immediately

Step 8: Verify

python
overview = gnosari_get(gnosari_id=gnosari_id)

print(f"Agent: {overview.name}")
print(f"Public URL: {overview.public_url}")
print(f"Knowledge sources: {len(overview.sources)}")
for source in overview.sources:
    print(f"  - {source.name}: {source.loading_status}")
print(f"Traits: {[t.name for t in overview.traits]}")
print(f"Data templates: {[t.name for t in overview.templates]}")
print(f"Hints: {overview.hints}")  # empty when fully configured

Flow Diagram

gnosari_create(name, instructions)

  gnosari_id returned + hints

gnosari_manage_instructions(replace/append)

gnosari_manage_knowledge(create+assign)   ← async loading starts

gnosari_manage_traits(assign)

gnosari_manage_data_collection(create+assign)

gnosari_manage_appearance(greeting, prompts, theme)

gnosari_check_uri(uri)  →  available?

gnosari_manage_access(PUBLIC, uri)

gnosari_get(gnosari_id)  →  hints=[]  →  fully configured

Monitoring Knowledge Loading

Knowledge sources load asynchronously. Check status via gnosari_get:

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

Typical loading times:

  • Small site (< 50 pages): 1–2 minutes
  • Medium site (< 500 pages): 5–10 minutes
  • Large site (> 1000 pages): 15–30 minutes

If a source fails, recreate it via gnosari_manage_knowledge(action="delete", source_id=...) then gnosari_manage_knowledge(action="create", ...).


Error Recovery

Each step is independent. If a step fails, fix and retry without repeating earlier steps.

FailureRecovery
Knowledge source creation failsRetry gnosari_manage_knowledge(action="create", ...)
URI conflict on publishUse gnosari_check_uri to find available alternative
Appearance update failsRetry gnosari_manage_appearance — earlier steps unaffected
Agent creation failsNo partial state — start with a new gnosari_create