What’s in it
Metrics
Business measures with definitions and formulas — revenue, CAC, ROAS — so
everyone (and every agent) computes them the same way.
Entities & records
The business objects you work with — campaigns, products, customers — and how
they map to the tables in your data sources.
Definitions & rules
The exact SQL behind a metric, how you segment “active users”, and mandatory
filters (like “exclude refunded orders”) agents must always apply.
Skills
Reusable procedures an agent can call to perform a task the same way each
time. Pin them to an agent to give it a capability.
What agents learn
Findings, limitations, and optimizations an agent picks up while working, kept
so it doesn’t relearn them.
Source notes
Caveats about a dataset or an API — its grain, freshness, known gaps, and
quirks — so agents read it correctly.
Read and update a record from the CLI or REST
The CLI returns the same full typed object used by the app, including its links, backlinks, related objects, and attachments:--title, --body, or --config to update an entry:
--config replaces the complete config object; include every setting
you want to keep, including tags and skill code. --body "" explicitly clears
the body, subject to the entry’s approval and visibility rules.
The CLI also sends the version it read. If another edit lands before the save,
the command returns HTTP 409 without overwriting that edit. Read the entry again,
review the new values, and retry your change.
Scoped API keys need resources:read to read entries and resources:write for
updates, visibility changes, deletion, or attachment uploads. The CLI update
command reads before saving, so its key needs both capabilities. The entry’s
existing workspace and access rules still apply.
The REST equivalents are GET /v1/knowledge/:id and
POST /v1/knowledge/:id/actions. For an update, send action: "update", the
complete title, body_markdown, and config_json, and copy the read response’s
object.updated_at into expected_updated_at:
expected_updated_at is optional for REST callers. Supplying it rejects stale
writes atomically; omitting it keeps unconditional update behavior. The same
precondition applies to the typed status, visibility, and resource binding actions.
Writes may include an optional agent name. Erdo trims and lowercases it, accepts
up to 64 letters, numbers, _, or -, and records it as authorship provenance.
The MCP tools erdo_get_knowledge and erdo_update_knowledge use the same
GET /v1/knowledge/:id and POST /v1/knowledge/:id/actions endpoints. Search,
list, and get records expose created_by_agent, last_changed_by_agent, and
last_changed_at; an update with agent is recorded as an agent change rather
than a manual edit.
When an agent reads a Knowledge record, the thread shows a deterministic label
with the record type and title, such as Read skill: Prospect outreach. The
label comes from the record returned by the read, so long record content cannot
turn the status into an invented outcome.
Linking knowledge
Use[[Title]] in a Knowledge entry or saved Shortcut prompt to link another
entry. After saving, open Links → Outgoing and follow the link to check the
entry it uses. Linked skills provide the saved Shortcut’s initial skill context.
The agent reads the full written instructions in selected Knowledge and persona
skills before planning searches or doing the task. Long instructions keep their final
steps. If required context cannot be loaded, the run stops so it cannot proceed
with missing instructions. This includes instructions saved for an automation when
they are explicitly selected for the run. Instructions for other automations are
not added through workspace defaults or background search. Skills with executable
code keep their normal runtime and language rules.
Links use current entries in your workspace first, then shared built-in entries.
Archived entries are excluded. If two current entries match in the preferred
scope, the link stays unresolved; give the intended entry a distinct title and
update the reference. Draft entries can be linked, but a link does not approve
their content. Saving the source again clears a stale automatic link when its
target has been archived or its name is ambiguous.
Starting from a template
When you start a template, the agent reads its instructions and checks relevant Knowledge and connected resources before asking for more information. It also researches your company website when the task calls for it. For a lead engine, it finds your Brand Style and published selling points; if there is no Brand Style yet, it captures one from your verified website. When a choice needs your input, the agent presents what it found: for example, “Use this Brand Style for the landing pages?” with the record identified. You still choose goals, budgets, optional features, and approve work at review steps. If information is private, ambiguous, or inaccessible, the agent asks for the specific missing detail.Tied to your data
Knowledge isn’t free-floating prose. A metric or entity is bound to the datasets it comes from — which table, at what grain, keyed on which columns, with which filters. That binding is what lets an agent move from “revenue is defined as…” to actually running the right query against the right table. One definition is marked the source of truth when several could apply, so agents don’t pick the wrong one. Already have this modelled elsewhere? Import it from dbt, LookML, Power BI, or Tableau and Erdo turns your metrics, entities, relationships, and access rules into knowledge. See Bring your semantic layer.Shared values with collections
Some facts are exact values that show up in many places at once — your monthly price, this quarter’s targets, brand tokens. Hardcoding them into each definition, skill, and page means they drift the moment one changes. Instead, store the value once in a KV store (a named collection — Erdo’s shared key/value store) and reference it from Knowledge prose as{{slug.key}}:
{{pricing.monthly}} becomes $29 everywhere, and
updating the store updates every record and page that references it. The same
KV stores are read by pages and
managed over the CLI and MCP/REST API.
References are permission-aware and fail closed: if a reference can’t be
resolved — unknown store, missing key, or no access — it renders as a visible
⟦unresolved: slug.key⟧ marker rather than a silent blank or raw braces, so a
broken reference is obvious instead of quietly wrong. References resolve when the
record is read, against the live KV value — so editing the store
updates every record at once.
Use it from your apps and tools
Knowledge isn’t only for agents in a thread. A page can read a knowledge object directly as structured app data —window.erdo.getKnowledgeObject(id)
returns the object plus its links, backlinks, and related objects, so an app can
render a brand profile, a metric definition, or a glossary straight from the Brain
instead of hardcoding it. And the same records are reachable over the
CLI (erdo knowledge list / search) and the
MCP/REST API (erdo_create_knowledge,
erdo_search_knowledge, …) — so coding agents and scripts read and write the same
shared brain your in-app agents use.
Images and files as org assets
An image attached to a knowledge object becomes an asset your published pages can render. The attachment’s id is exactly what a page’sassetId refers to, so the
brand imagery on your Brand Style record and the hero on a live landing page are
the same object — replace the asset and every page pointing at it follows.
The Brand Style record’s colours travel just as far: an agent drawing a chart in
a conversation styles its series from that palette, so the record is what keeps
your pages and your answers looking like the same company. See
Charts and tables in the conversation.
Attach one from the CLI:
asset_id to reference. Large files and video don’t travel well as
request bodies, so pass --url instead and Erdo downloads the file itself,
streaming it straight to storage. The same capability is
POST /v1/knowledge/:objectId/attachments over REST and erdo_attach_knowledge_asset
over MCP, so a script or a coding agent can register an image without a trip
through the web app.
List the files on an object with erdo knowledge assets list <objectId>,
GET /v1/knowledge/:objectId/attachments, or the MCP tool
erdo_list_knowledge_assets. Each result includes a signed download URL and
the attachment’s public visibility; incomplete: true means a transient
public-grant or signing lookup could not be resolved for every file.
Write a description whenever you can. For an image, that caption is the only text
a search can match — an uncaptioned IMG_4821.jpg is findable by its filename and
nothing else. Erdo captions uncaptioned images in the background, but a caption in
your own words describes what matters about the picture rather than what is
visible in it.
How agents use it
As agents work, they lean on Knowledge in two directions:- Search before acting — before answering or running code, an agent searches Knowledge for your definitions, skills, and prior learnings, so it uses your meaning of a term instead of guessing.
- Propose after learning — when an agent learns something durable (“this column is the revenue metric”, “this API caps page size at 100”), it proposes adding it to Knowledge so the next thread benefits.
Visibility — workspace vs. public
Every Knowledge entry has a visibility that controls who it can be shown to:- Workspace (the default) — visible to people and agents inside your organization only. Nothing you add is exposed externally unless you say so.
- Public — the entry is opted into anonymous external surfaces, such as the website voice widget answering visitors on your site. Making an entry public is the publish decision: a draft is approved in the same step and goes live immediately, so only flip it when you mean it.
erdo knowledge list --public
from the CLI, or GET /v1/knowledge?visibility=public from the API. Each
agent’s Knowledge tab also shows the same public set, since that’s what its
website deployments answer from.
Reserve Public for customer-facing facts you’d happily tell any visitor:
products, pricing, opening hours, locations, policies, FAQs, galleries. Internal
processes, personal data, and financials stay Workspace.
Keeping facts fresh
Some knowledge goes stale — an API version changes, an enum is renamed, a rate limit moves. Erdo tags volatile facts with when they were last verified and when they should be re-checked, and marks them deprecated or superseded when they’re replaced. Agents treat stale or unverified facts as a hint to confirm, and always prefer current tool definitions and live docs over an old note.Running a saved Shortcut over the API
Read the full saved record withGET /v1/knowledge/{id} or
erdo shortcut get <id> to inspect config_json and its related Knowledge.
Run it through the existing POST /v1/ask:
project_id, the authenticated active project
must match it; select that project with X-Project-ID or the CLI’s --project.
Missing or different scope fails before creating a thread. Saved configuration
cannot override the caller’s authorized scope.
Archived, deleted or inaccessible Shortcuts fail. Every outgoing Knowledge
reference must resolve to a current object that you can view in the workspace
or through public access. An unresolved, missing, archived or inaccessible
target blocks startup before a thread or message is created, even when other
linked skills are available. The error does not disclose an inaccessible target’s
identity or type. Repair the link or its access and run the Shortcut again.
Known accessible objects of other types are not pinned as skills. Incoming links
and bindings to other resources do not count as declared Knowledge context.
The Knowledge read returns declared_context_status: complete or unknown.
Both normal interactive runs and API runs check the current saved context.
Missing configured datasets or missing attachments for the projected skill pins
also fail before invocation. Do not combine saved_ask_id with question,
dataset_slugs or images. Free-question calls retain those fields.
parameters is optional flat data with string, finite number, boolean or null
values. Keys must start with a letter or underscore and contain only letters,
digits or underscores, up to 64 characters. Its serialized size is at most 4096
characters. These values are appended as untrusted invocation data; they cannot
override saved configuration.
An asynchronous response identifies the new thread_id and persisted user
message_id, with status: "running" after durable startup. Poll
GET /v1/runs?thread_id=... for terminal status and read the workflow’s canonical
records for its result. Each call starts a new thread; a timeout or lost response
is not evidence that nothing started. The CLI does not automatically replay it.

