Brand context tools
The Brand Knowledge Base is a per-brand store of durable context: a typed profile, prose sections on positioning and voice, a list of named competitors, and learnings that accumulate over time. An agent reads it before analysis so its recommendations are anchored in what your brand actually cares about, and writes to it directly with the tools on this page.
You can also view and edit the Knowledge Base by hand in the dashboard. See Brand Knowledge Base.
Read the Knowledge Base
Section titled “Read the Knowledge Base”get_brand_context
Section titled “get_brand_context”The preflight call. Call this before asking an agent to analyze data or write a report, so it knows whether the data is current and trustworthy, and what the brand’s targets and voice are.
get_brand_context(brand: str | None = None) -> dict| Parameter | Type | Description |
|---|---|---|
| brand | string | Brand name or id. Required only when the caller can reach more than one brand; auto-selected otherwise. |
The response bundles the Knowledge Base together with operational fields (connection status, a data readiness check, and data coverage) used for that same preflight - see Data tools for those. The Knowledge Base portion of the response:
| Field | Description |
|---|---|
| context | The typed profile: vertical, price_tier, margin_band, target_roas, target_cpa, target_aov. Any field can be null. |
| sections | Array of {key, content_md, updated_at} - the four prose sections described below. |
| competitors | Array of {name, handle, differentiator}. |
| learnings | Array of {id, topic, content, evidence}. Active learnings only. |
| learning_cap | {active, cap} - how many active learnings exist against the soft cap. |
| is_empty | true only when the profile, sections, competitors, and learnings are all unset. |
Write to the Knowledge Base
Section titled “Write to the Knowledge Base”Six tools cover the Knowledge Base’s four parts.
Each takes an optional brand argument with the same rule as get_brand_context, and each requires your OAuth login or API key to carry write scope (see API keys).
Because they change stored data, most MCP clients prompt you to approve each call before it runs; remove_competitor is marked as a stronger, destructive action since it deletes a row.
update_brand_profile
Section titled “update_brand_profile”Partial update to the typed profile. Only the fields you pass are changed.
update_brand_profile( vertical: str | None = None, price_tier: str | None = None, margin_band: str | None = None, target_roas: float | None = None, target_cpa: float | None = None, target_aov: float | None = None, clear: list[str] | None = None, brand: str | None = None,) -> dict| Parameter | Type | Description |
|---|---|---|
| vertical | string | Free-text category, for example “skincare”. |
| price_tier | string | One of value, mid, premium, luxury. |
| margin_band | string | One of lean, moderate, healthy. |
| target_roas | number | Target return on ad spend. |
| target_cpa | number | Target cost per acquisition. |
| target_aov | number | Target average order value. |
| clear | list of strings | Profile field names to unset. |
| brand | string | Brand name or id. |
An invalid price_tier or margin_band value is rejected rather than saved.
update_section
Section titled “update_section”Creates or replaces one prose section. This is a full replace, not a merge with the existing content.
update_section(key: str, content_md: str, brand: str | None = None) -> dict| Parameter | Type | Description |
|---|---|---|
| key | string | One of positioning, icp, competitive_landscape, brand_voice. |
| content_md | string | The section’s content, as markdown. |
| brand | string | Brand name or id. |
There is one row per key per brand.
Writing an unrecognized key is rejected.
set_competitor
Section titled “set_competitor”Adds a competitor, or updates one if the name already matches.
Matching on name is case- and spacing-insensitive, so writing “glossier” updates an existing “Glossier” row instead of creating a duplicate, and the stored name’s casing is refreshed to whatever was just written.
set_competitor( name: str, handle: str | None = None, differentiator: str | None = None, clear: list[str] | None = None, brand: str | None = None,) -> dict| Parameter | Type | Description |
|---|---|---|
| name | string | The competitor’s name. Used to match an existing row. |
| handle | string | Handle or URL. |
| differentiator | string | A one-line note on how they differ from this brand. |
| clear | list of strings | handle and/or differentiator, to unset them. |
| brand | string | Brand name or id. |
On an existing competitor, any field you don’t pass is left unchanged.
remove_competitor
Section titled “remove_competitor”Permanently deletes a competitor by name, using the same case- and spacing-insensitive match as set_competitor.
remove_competitor(name: str, brand: str | None = None) -> dict| Parameter | Type | Description |
|---|---|---|
| name | string | The competitor’s name to remove. |
| brand | string | Brand name or id. |
If no competitor matches, this is not an error: it returns the current list of competitor names so the agent can retry with the right one.
record_learning
Section titled “record_learning”Creates a new learning, or updates an existing one in place when you pass its id.
record_learning( topic: str, content: str, evidence: str | None = None, id: str | None = None, clear: list[str] | None = None, brand: str | None = None,) -> dict| Parameter | Type | Description |
|---|---|---|
| topic | string | What the learning is about. |
| content | string | The insight itself. |
| evidence | string | What supports it, optional. |
| id | string | Omit to create a new learning. Pass an existing learning’s id to update it instead. |
| clear | list of strings | Only "evidence" can be cleared this way. |
| brand | string | Brand name or id. |
Creating a new learning (no id passed) returns related: the brand’s existing active learnings on the same topic, matched case- and spacing-insensitively.
A non-empty related list is a signal to merge into one of those instead of keeping a near-duplicate, by calling record_learning again with that learning’s id.
Updating by id always returns an empty related list.
Active learnings are capped at 50 per brand as a soft signal, not a hard limit: writes are never blocked at the cap, but it’s a cue to archive stale ones.
Check learning_cap from get_brand_context to see where a brand stands.
archive_learning
Section titled “archive_learning”Soft-archives a learning, removing it from the active set and the learning_cap count.
archive_learning(id: str, brand: str | None = None) -> dict| Parameter | Type | Description |
|---|---|---|
| id | string | The learning’s id. |
| brand | string | Brand name or id. |
There is no unarchive tool. Archiving is a one-way move from an agent’s perspective; restoring a learning means recording it again.
Need help?
Section titled “Need help?”Email support@kreel.ai.