All articles
Vision & Category·September 22, 2025·7 min read

Personas as Data, Not Code: Ship an Agent by Filling Out a Form

In Matrix there are no hardcoded personas. An agent is a configured record you create through a form or one POST — no code, no redeploy, persisted in Neo4j.

By Matrix Team

Most "agent frameworks" ship with a personality baked into the source tree. There's a SupportAgent class, a system prompt in a .py file, a switch statement that routes "the astrologer" to one code path and "the tutor" to another. Want a new kind of agent? Open a PR, rebuild, redeploy, and hope you didn't break the other three.

Matrix takes the opposite stance, and it's the single most consequential design decision in the platform: there are no hardcoded personas. Not one. A kindergarten teacher, a recruiter, a retention rep, a tutor, a data analyst, an astrologer — every single one is the same thing under the hood: a configured record. You create it by filling out a form.

This post is about why that matters for the people deciding whether to build or buy, and what it actually looks like to ship an agent without writing a line of code.

An agent is a row, not a class

Everything in Matrix — Organization, Team, User, Agent, Skill, Knowledge, Tool, Session, Memory — is modelled as a generic EntityType / EntityNode in Neo4j. There are no hand-rolled @Node classes per domain. An Agent isn't special: it's an EntityNode with a known set of properties, stored next to everything else in the graph.

That has a concrete, boring, enormously valuable consequence: creating an agent is a database write, not a deployment. You add a record. The agent exists. It persists across restarts because it lives in Neo4j, not in a config file someone forgot to mount into the container. Wipe the running process, bring it back up, the agent is still there.

This is the "no-code ai agent builder" claim, and it's not marketing — it's the architecture. If the only way to add a persona is to write a row, then by definition no code change is needed to add a persona.

Two ways to create one

You ship an agent through the admin dashboard or the API. Pick whichever fits your workflow.

The form. Go to /orgs/{slug}/admin/agentsNew agent. You get a drawer: name it, write the system prompt, pick a voice, attach skills and knowledge with pickers, set the fields the agent should learn about a caller. Save. Done. That's the whole motion — it's the one in the comparison table that reads "New persona: fill out a form" instead of "ship code."

The POST. Same thing, scriptable:

POST /api/orgs/{slug}/agents
{
  "properties": {
    "key": "retention-rep",
    "name": "Renewal Specialist",
    "systemPrompt": "You are a friendly subscription-retention rep. Find out why the customer is thinking of cancelling, address the concern honestly, and offer the most relevant retention option.",
    "voice": "Kore",
    "requiredCallerFields": "name,plan,renewalDate",
    "skills": [/* skill ids */],
    "knowledge": [/* knowledge ids */]
  }
}

No subclass. No route registration. No redeploy. The agent is live and addressable by its key over chat, voice, and autonomous tasks — the same composed prompt drives all three channels, byte-for-byte, so the agent behaves identically no matter how someone reaches it.

What the agent actually is at runtime

Here's the part that makes "personas as data" more than a storage trick. The agent's behaviour on any given turn is composed, not authored in one place. The final system prompt is:

Agent.systemPrompt
  + each attached skill's systemPromptBlock
  + the universal "always learn about the contact" block

Three layers, assembled per turn from live entity rows:

  • Agent.systemPrompt is the persona you wrote in the form — who this agent is, its tone, its job.
  • Each attached Skill's systemPromptBlock folds in reusable behaviour. A skill is a bundle: a prompt augmentor, tool references, memory-field requirements, and optional bundled files. Attach the seeded toolkit-essentials skill and your agent gains the whole built-in toolbox (web_search, fetch_url, bash, file_*, grep). Import a community skill from any GitHub SKILL.md and it slots into the same composition.
  • The universal "always learn about the contact" block is added to every agent automatically. It's the platform's built-in memory discipline — the agent is told to learn about whoever it's talking to, and it's handed the memory tools to do it.

Because this composes per turn from the live entities, editing the persona — or approving a self-improvement proposal — takes effect on the agent's next turn. No redeploy, no restart.

If you want the full picture of how Tool, Skill, Knowledge, and the built-in Toolbox combine, that's its own post: Composing Agents From Four Primitives.

The form fields that matter

A few configuration fields punch above their weight.

Attach Skills and Knowledge in the drawer

The agent drawer has pickers for Skills and Knowledge. Attach a Knowledge corpus — a per-org RAG store you built by dragging a PDF into the browser — and the agent automatically gets a search_knowledge tool, corpus-scoped, no plumbing. Attach a skill and you pull in its prompt block, its tools, and its required contact fields, all unioned into the agent's surface. You're not writing integration glue; you're checking boxes.

requiredCallerFields

Set requiredCallerFields to a CSV of the things this agent needs to know about a caller — dateOfBirth,birthTime,birthPlace for an astrologer, name,plan,renewalDate for a retention rep. The runtime turns that into a "what you still need to learn" checklist in the prompt, and the built-in memory tools save the answers as the conversation gives them up. It's how you make an agent gather the right information without scripting an interrogation.

Voice

Pick one of eight Gemini Live prebuilt voices: Aoede, Charon, Fenrir, Kore, Puck, Orus, Leda, Zephyr. That's the entire voice configuration. The same agent record drives both the telephony bridge and the browser-direct voice page.

"But surely the demo personas are special?"

They're not, and that's the proof. Matrix ships an optional AI-Astrologer demo pack — 7 Vedic personas plus a set of panchang tools — behind the MATRIX_DEMO_SEED flag, default off. When you flip it on, a seeder writes those agents into a demo org on boot.

Look at how it's built and you'll see it's data on top of the same schema everyone else uses. The demo seeder doesn't introduce a new agent type or a special code path; it writes the same EntityNode rows you'd write through the form, just from a seed file instead of the UI. It's a worked example of how to build a domain-specific agent set on top of the platform — not the platform itself. The platform has no idea what an astrologer is. It only knows how to compose an agent from its configured record.

That's the cleanest possible demonstration of the principle: the most elaborate persona set in the codebase is still just data, opt-in, and removable by leaving a flag off.

Why a Decider should care

Three things, all about leverage.

Time-to-value collapses. The unit of work for a new agent goes from "engineering ticket → PR → review → deploy" to "fill out a form." Your ops team, your product team — anyone who can describe an agent in plain language can ship one. Engineering stops being the bottleneck for every new persona.

The blast radius shrinks. When personas are code, every new agent is a chance to break the existing ones and a reason to schedule a deploy. When they're data, agents are isolated rows. Adding the tenth agent can't regress the first nine, because nothing was recompiled.

The core stays generic — and that protects you. Everything under the platform's source tree is strictly domain-agnostic. Your domain lives in data: personas, prompts, custom fields, tools. You never fork the platform to add your business logic, which means you can take upstream improvements without rebasing a pile of local patches. This is the difference between buying a platform and adopting a framework you'll slowly turn into a fork.

If you're weighing that trade-off at the architecture level, start with Why AI Agents Need a Platform, Not a Framework.

Takeaway

A persona is not a feature you build — it's a record you configure. In Matrix, an agent is an EntityNode: created through /admin/agents or one POST, composed per turn from its system prompt + attached skills + the universal contact-learning block, and persisted in Neo4j across restarts. The fanciest demo in the repo is opt-in data on the exact same schema. If you can describe the agent you want, you can ship it — no code, no redeploy.

Ship one

Create a workspace, open /orgs/{slug}/admin/agents, click New agent, and have a working agent on chat and voice before your coffee's cold. Or script it with a single POST /api/orgs/{slug}/agents. Worked examples live in the repo's scripts/ directory, and there's a full curl walkthrough in docs/RUNBOOK.md. Build your first agent — by filling out a form.

#no-code ai agent builder#agents#configuration

Build your first agent on Matrix

Spin up a workspace, wire up tools and knowledge, give your agent a voice, and talk to it in real time — no agent code required.

Keep reading