Appearance
Agent Builder
This guide explains the chat-style agent-builder workflow in SwarmForge, including the SDK conversation loop and the HTTP authoring transport. It does not explain general swarm graph authoring or runtime orchestration in depth.
This guide is for developers building an app experience where users describe an assistant, answer a few follow-up questions, confirm the direction, and then stream prompt generation progress back into the UI.
After reading this guide, you should be able to:
- run the agent-builder lifecycle directly in Python
- persist and restore
AgentBuilderSessionacross turns - model a chat-like onboarding flow in your frontend
- expose the same flow over FastAPI with the authoring transport
- run the one-shot voice-agent prompt builder from a typed spec
Lifecycle overview
AgentBuilderFlow manages a staged lifecycle:
- readiness analysis
- onboarding plan generation
- conversational onboarding turns
- generation confirmation
- staged prompt generation
The main session object is AgentBuilderSession. It is the state container your app keeps between turns.
SDK chat loop
Use the SDK directly when your backend already owns the conversation loop and just needs a clean Python abstraction.
python
from swarmforge.authoring import AgentBuilderFlow
flow = AgentBuilderFlow()
start = flow.start_onboarding(
"Build me a LinkedIn outbound agent for B2B SaaS demo booking"
)
if not start.ready:
print({"type": "clarification", "message": start.clarifying_question})
else:
session = start.session
print({"type": "assistant", "message": start.opening_message})
turn = flow.process_onboarding_turn(
session,
(
"It should prospect founders by LinkedIn DM, qualify interest, "
"and book meetings for our account executives."
),
)
print({"type": "assistant", "message": turn.reply, "stage": turn.stage})
if turn.all_fields_collected:
confirm = flow.process_confirmation_turn(session, "yes, generate it")
print({"type": "assistant", "message": confirm.reply, "stage": confirm.stage})
if confirm.confirmed:
result = flow.run_generation(
session,
generate_tools=True,
tools_format="openai",
)
print(result.prompt_title)
print(result.meta_prompt)Persist session state between chat turns
The frontend or API layer should treat the session as durable conversation state. Store session.to_payload() after each turn and restore it with AgentBuilderSession.from_payload(...) before the next SDK call.
python
from swarmforge.authoring import AgentBuilderSession
session_payload = session.to_payload()
# Persist session_payload in your database, cache, or client state.
restored_session = AgentBuilderSession.from_payload(session_payload)This keeps the chat loop stateless at the HTTP layer while preserving onboarding progress, collected answers, step status, and prior assistant messages.
Chat-style frontend pattern
For a chat UI, the cleanest pattern is:
- call
start_onboarding(...)orPOST /v1/authoring/agent-builder/start - render
opening_messageorclarifying_question - on each user reply, send the latest serialized
sessionplususer_message - replace your stored session with the returned
session - when the stage becomes
confirm_generate, ask for explicit approval - after confirmation, call
generateorgenerate/stream
The most important rule is to reuse the returned serialized session rather than reconstructing builder state in the client.
FastAPI authoring transport
Use create_authoring_app(...) when you want the same lifecycle over HTTP.
python
from swarmforge.api import create_authoring_app
app = create_authoring_app(title="SwarmForge Authoring API")Source example: examples/fastapi_authoring_server.py
Run from the repository:
bash
python examples/fastapi_authoring_server.pyInstalled-package entrypoint:
bash
uvicorn swarmforge.api.authoring:create_authoring_app --factory --reloadRoute sequence for a conversational builder
The authoring transport exposes a narrow route surface:
POST /v1/authoring/agent-builder/startPOST /v1/authoring/agent-builder/onboarding-turnPOST /v1/authoring/agent-builder/confirmPOST /v1/authoring/agent-builder/generatePOST /v1/authoring/agent-builder/generate/streamPOST /v1/authoring/agent-builder/runPOST /v1/authoring/agent-builder/voice/run
Typical chat flow:
startwith the initial user requestonboarding-turnfor each conversational replyconfirmonce the session reachesconfirm_generategenerate/streamfor live phase updates, orgeneratefor one final payload
Start a builder conversation
bash
curl -X POST http://127.0.0.1:8000/v1/authoring/agent-builder/start \
-H 'Content-Type: application/json' \
-d '{
"seed_request": "Build me a refund support assistant for ecommerce web chat."
}'If the request is specific enough, the response includes:
opening_messagereadinesssession
If the request is still vague, the response returns ready: false plus a clarifying_question.
Continue the conversation
bash
curl -X POST http://127.0.0.1:8000/v1/authoring/agent-builder/onboarding-turn \
-H 'Content-Type: application/json' \
-d '{
"session": {"seed_request": "...", "topic": "...", "category_type": "persona", "category_label": "Support Agent Builder", "onboarding_prompt": "...", "stage": "onboarding", "collected_inputs": {}, "fields": [], "steps": [], "messages": []},
"user_message": "It should resolve refunds quickly in web chat and escalate risky disputes."
}'Each conversational reply returns:
replyextracted_fieldsall_fields_collectedstage- updated
session
Confirm and stream generation
Once the session reaches confirm_generate, ask the user for an explicit yes/no. Then call the confirmation route and start streaming generation.
bash
curl -N -X POST http://127.0.0.1:8000/v1/authoring/agent-builder/generate/stream \
-H 'Content-Type: application/json' \
-d '{
"session": {"seed_request": "...", "topic": "...", "category_type": "persona", "category_label": "Support Agent Builder", "onboarding_prompt": "...", "stage": "generating", "collected_inputs": {"intent": "Resolve refunds quickly"}, "fields": [], "steps": [], "messages": []},
"generate_tools": true,
"tools_format": "openai"
}'The SSE stream emits:
startphasegeneration_resultsessiondoneerror
Use phase events to update progress UI and generation_result as the final prompt payload to store or display.
One-shot builder flow
Use run_full_flow(...) or POST /v1/authoring/agent-builder/run when your app is form-first rather than chat-first.
That path is better when:
- the UI already has a multi-field wizard
- you do not need adaptive follow-up prompts in the client
- you want one request that runs planning plus generation end to end
If you are building a conversational product experience, prefer the chat-style loop because it lets the builder ask for the next highest-value detail instead of forcing a rigid form.
One-shot voice-agent prompt builder
Use generate_voice_agent_build(...) or POST /v1/authoring/agent-builder/voice/run when the UI already has a complete structured voice-agent spec and should generate the prompt plus related artifacts in one request.
This path is intentionally separate from generated agent code. It produces prompt-building artifacts only:
system_prompttools_schemacall_flowsummary_schemaeval_scenariosresearch_summary,sources, andprompt_title
The voice build spec includes the same core call-building fields as the conversational builder, plus dedicated voice-specific sections:
business,call,use_case,knowledge_base,integrations,tools, anddata_collectionbehaviorfor phone-conversation style, such as short turns and one question at a timeguardrailsfor safety rules, refusal rules, forbidden actions, disallowed topics, confirmation requirements, tool-use rules, fallback response text, hallucination policy, and tool retry limitscompliance,escalation,voice_runtime, andquality
SDK example
python
from swarmforge.authoring import VoiceAgentBuildSpec, generate_voice_agent_build
spec = VoiceAgentBuildSpec(
template={"id": "real_estate_voice", "category": "voice_call_agent"},
business={
"company_name": "Atlas Realty",
"industry": "real estate",
"market": "Casablanca",
"languages": ["en", "fr", "ar"],
"brand_tone": "professional and concise",
},
call={
"direction": "inbound",
"main_goal": "qualify property buyers and book viewings",
"target_caller": "property buyer",
},
knowledge_base={
"enabled": True,
"knowledge_base_ids": ["properties"],
"search_required_for": ["availability", "pricing"],
},
tools={
"generate_tools": True,
"allowed_tool_types": ["function", "apiRequest", "query", "sms", "endCall", "webhook"],
"required_logical_tools": ["book_viewing", "send_sms_confirmation"],
},
data_collection={"required_entities": ["name", "phone", "budget", "preferred_location"]},
guardrails={
"safety_rules": ["Do not provide legal, medical, or financial advice."],
"refusal_rules": ["Refuse requests to bypass identity, consent, or booking rules."],
"forbidden_actions": ["Do not promise property availability without checking tools."],
"confirmation_required_for": ["booking", "sms", "crm_update", "call_transfer"],
"tool_use_rules": ["Use knowledge search before answering pricing or availability questions."],
},
)
result = generate_voice_agent_build(spec, tools_format="openai")
print(result.system_prompt)
print(result.tools_schema)HTTP example
bash
curl -X POST http://127.0.0.1:8000/v1/authoring/agent-builder/voice/run \
-H 'Content-Type: application/json' \
-d '{
"tools_format": "openai",
"spec": {
"version": "1.0",
"template": {"id": "real_estate_voice", "category": "voice_call_agent"},
"business": {
"company_name": "Atlas Realty",
"industry": "real estate",
"languages": ["en", "fr", "ar"]
},
"call": {
"direction": "inbound",
"main_goal": "qualify property buyers and book viewings"
},
"tools": {
"generate_tools": true,
"allowed_tool_types": ["function", "apiRequest", "query", "sms", "endCall", "webhook"],
"required_logical_tools": ["book_viewing"]
},
"guardrails": {
"safety_rules": ["Do not provide legal, medical, or financial advice."],
"confirmation_required_for": ["booking", "sms", "crm_update"]
}
}
}'