Cookbook
Design principles · for AI agents

Design principles — read this first

How to configure agents that actually work — one job per agent, few skills, grounded, verified.

MCP tools:get_agentsearch_knowledge_base

Most "the agent gives bad answers" problems are configuration, not the model. Follow these before you build, and the results hold up. Ignore them and it is easy to assemble something that looks plausible and behaves badly — then mistake that for a platform limit.

Discover before you build — interview, don't just execute

"Create a support agent" is the start of the conversation, not the spec. Never answer it with a single create_agent and hand back a blank shell. Work like the setup wizard: interview first, plan the whole setup, play it back, then build. Ask in plain language — a few questions at a time, about their real situation, not tool parameters — until you can picture the finished thing:

  • The job & who it serves. What is this agent for, who talks to it, what does a good answer look like? One job per agent — if they describe three, that's three agents.
  • What it must answer from → a knowledge base. Do they have documents, a site, policies, a price list? If facts have to be right, those become a knowledge base you build and attach — not prompt text. If they have nothing yet, tell them what to gather.
  • Procedures it runs → skills. Any "when X, do these steps" behaviours (book, screen, quote)? Each becomes a load-on-demand skill with a sharp "use this when…".
  • Things it must do in other systems → MCP. Check a calendar, look up an order, open a ticket? Those are MCP tools to bind — ask which system and whether they can connect it.
  • A guided, stateful flow → a Storyline. Is it a process with memory (intake → qualify → follow-up) rather than one-shot Q&A? That's a Storyline, not just an agent.
  • How it opens and its hard limits. The first line visitors see (→ a page playbook) and the boundaries that go in task ("never quote a price", "never give legal advice").

Then play the plan back before touching a tool — "so I'll build: agent Support, a knowledge base from your policy PDFs, a booking skill, and bind your calendar over MCP — right?" — and build only once they confirm. Skipping this is exactly how you end up with an empty agent nobody wanted. A vague request is a cue to ask, never a cue to guess.

One agent, one job

Give each agent a single, clearly bounded task. A "does everything" agent — support and sales and scheduling — has a diffuse task, competes with itself for attention, and answers each thing worse. If you have three jobs, build three agents.

Keep the skill count small

Attach only the skills this agent's job needs — roughly five or fewer. Skills are chosen by the model from their one-line description; the more you attach, the harder that choice, and the more often it loads the wrong one or none. A focused set with sharp "use this when…" descriptions beats a big pile.

  • Each skill's description says when to reach for it, in one line.
  • Procedures live in instructions (loaded on demand), never in soul (paid for every turn).
  • If two skills overlap in when, merge them — overlapping triggers make the choice a coin-flip.

Ground facts; put boundaries in the task

  • Facts (rates, policy, catalogue) belong in a knowledge base, which is retrieved every turn — not in the prompt, where they go stale and un-cited. See Build a knowledge base.
  • Constraints belong in task, as negatives: "never promise a date", "for a quote, call a tool". Negative boundaries stop drift better than positive description. Don't put safety rules in soul — the platform appends global moderation for you.
  • Turn on grounding_required when answers must come from the material, not the model's priors.

Never hand determinism to probability

The single most useful design rule on this platform: if something can be computed, generated, or verified by the system, never leave it to the model. A model asked to produce a deterministic artifact doesn't fail loudly — it produces a plausible one. The user gets a ticket number that doesn't exist, a callback booked seven hours off, a colour palette that fails contrast. Nothing errors; it's just quietly wrong.

Every one of these started as a real production failure and became a platform feature:

Deterministic thingWrong way (probability)Right way (system)
Reference / ticket numbersInstructions say "tell the user the ticket number" → model invents onesave_contact / schedule_followup return a real stored code — instruct the model to relay it verbatim
Absolute timesModel hand-computes delay_seconds for "tomorrow 10am" → off by hoursPass run_at (local ISO time); the server resolves the timezone
Text colours on a brand colourModel picks "matching" colours → unreadable in one themeSend theme_color only; WCAG-contrast foregrounds are derived server-side
Routing in a flowAn ai exit for "if the user agreed"rule / user_choice exits; reserve ai exits for genuine judgment. Loops get an explicit counter and cap — never "the LLM will stop eventually"
"Did the trigger fire?"Assume the prompt workstest_skill_trigger measures it; the platform also injects a deterministic hint when a phone/email is detected
The wording that reaches a toolHope the model turns "any others like that?" into the right callThe platform works out what was asked, then composes the instruction from the tool's own definition and shows that turn one tool. Measured 80% → 97%; letting the model rewrite its own request did nothing (82%)
A phrase that must never appearAdd another "do not say X" line to the promptDelete it after the fact. A rule you can check on the finished answer is a rule you can enforce; a rule in the prompt is a request
Machine-readable output"Reply with valid JSON only" and parse strictlyAsk for the shape, then parse for the one field that matters. Strictness throws away answers that were right

The corollary for writing skills: your instructions should tell the model which system facility to use ("pass run_at, relay the returned code"), not teach it to imitate the facility ("compute the seconds, format a ticket number"). If you find yourself scripting the output of a deterministic process, look for the tool that produces it — or ask for one.

Two corollaries about output

A prompt rule is a request; a post-check is a rule. "Never say X" belongs in the prompt — it lowers the rate — but it is not enforcement. A model that agrees with the instruction can still reach the same forbidden idea by a phrasing your wording didn't anticipate, and each rewrite of the rule tends to catch only the phrasings you already saw. Wording cannot police wording. So ask a different question: is the unwanted sentence recognisable in the finished answer? If it is, remove it there, and keep the prompt line as well.

Get the content right first; do not let syntax cost you the content. A smaller model will often make the correct choice and then write it in a shape your parser rejects — one object per line instead of an array, a trailing comma, prose wrapped around the block. Parsing strictly means a correct answer is discarded for a misplaced brace, and the symptom looks like a model that isn't capable enough. Decide which field in the response is load-bearing — usually exactly one: an id, a reference, a choice — and extract that field however it arrives. The rest of the payload is typically data you were going to replace with your own anyway, so strictness about it protects nothing.

Show the agent good patterns only

When you hand an agent examples, make them correct examples. Don't paste a "here's the wrong way" snippet next to the right one — the model may imitate the nearest example rather than read the caveat. Describe what to avoid in words; keep runnable examples exemplary.

Verify — writing is not working

After every change, check it did what you intended. Creating an agent doesn't mean it's configured the way you think; adding to a knowledge base doesn't mean the question retrieves.

get_agent(name="Support")                                   # confirm the config that landed
search_knowledge_base(kb_name="Company policy", query="…")  # confirm the answer is retrievable

An empty search result means that question will be answered as "not covered" — find that now, not from a customer.

Hand back a deliverable — and the next step

After every action, don't just report that you finished. Hand back four things: what you produced, a clickable console link to view it, one line on how to use it, and the natural next step — proposed, and offered to do. They will ask "where do I see it?", "how do I use it?" and "what now?" anyway; answer all three up front. URL-encode names that contain spaces.

After you…Hand back
Create or import into a knowledge baseIts page — which includes the knowledge starmap (a 3D view of what was ingested): https://console.agent4.io/#/knowledge-bases/<name>
Create an agentIts page to review/test: https://console.agent4.io/#/agents/<name> — and note that to let end users reach it, they create a share link in the console
Create a skillhttps://console.agent4.io/#/skills/<name>
Publish a Storylinehttps://console.agent4.io/#/storylines/<id> (the id from create_storyline)
Register an MCP serverhttps://console.agent4.io/#/mcp/<id>

For example, after importing documents into a knowledge base, reply with how many chunks landed, the link above so they can open its knowledge starmap and see exactly what was ingested, and confirm whether it's now attached to an agent (or how to attach it). A bare "done" just makes them ask.

Always end on the next step, and offer to do it — a setup is a chain, not a single action:

  • Built a knowledge base? → offer to attach it to an agent (ask which).
  • Created an agent? → offer to attach a knowledge base, add a skill, or create a share link so end users can reach it (an empty space = off).
  • Authored a skill? → offer to attach it to the agent that needs it.
  • Published a Storyline? → offer to set it as the agent's default, or wire its enrollment trigger.
  • Registered an MCP server? → offer to grant an agent its tools.

"Here's what I made, here's the link, here's how to use it, and here's what I'd do next — want me to?" keeps the build moving; a bare "done" leaves the tenant guessing.