Space Apps
Space MCP tools in the Space Apps scope (apps). Reach these with a wks_live_ key over space-mcp or space-api.
Tools in the apps scope, callable over space-mcp (tools/call) or space-api (REST) with a wks_live_* key that grants apps.
check_app_door
Scope: apps:read
Check that an app here receives a kind of data: whether its door works, which collection it lands in, and what one item becomes there. Use it after adding "receives" to an app's schema.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
kind | string | yes | hook, tip, mistake, number, story, quote, research, playbook, post, script, idea, contact or product. |
create_app
Scope: apps:write
Create a new agent-authored Space App (trust_tier='user'). STANDALONE RULE: the app's core function must work for a human with your computer OFF — wire generation through wakato.gateway.* (billed/attributed to the APP), and declare any genuinely machine-dependent work in app_schema.agent_features (a portable feature contract: label + executable instructions + machine_requirements) instead of silently doing it yourself and inserting records. Declare required_capabilities in app_schema; the app holds what it declares from the moment it is saved (no approval step — the owner can take one back in the App Inspector). Authoring is free — no wallet charge. ui_code is VALIDATED on save (real JS syntax check + runtime-fatal lint) and rejected with actionable errors if broken. Required workflow: get_app_sdk_reference → create_app → test_app (actually run it) → publish_app.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
description | string | ||
icon | string | Lucide icon name, e.g. 'Sparkles'. | |
color | string | Hex color, e.g. '#5B4CDB'. | |
ui_code | string | Full HTML document or fragment (Preact+HTM). Uses the window.wakato.* SDK — call get_app_sdk_reference first for the full method list. | |
app_category | app | game | ||
app_schema | object | { data_models: {...}, required_capabilities: ["data.query", "gateway.llm", ...], pipelines: {...}, agent_features: { key: { label, instructions, inputs?, outputs?, machine_requirements? } } — agent_features declare computer-dependent work ANY agent can execute from the contract } | |
agent_guide | string | Optional guide for agents: plain text (up to 20,000 characters) on how to work in THIS app, returned first by get_app to any agent that opens it. Write one when the app is meant for agents to work in: what it is for, how to start (which records to create first), what each model/section means and what goes in it, how to read the person's decisions (what they approve, pick, note), which buttons send a message to the agent, and what never to do. Leave it out for an app people use on their own. |
create_app_data_record
Scope: apps:write
Create a record in a Space App's data store under a model — or up to 200 records of that model in one call with records. Each record's fields should match the app's schema for that model.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
model_key | string | yes | |
record_data | object | The record fields (per the app's model schema). | |
records | object[] | Several records of this model at once (max 200); each item is one record's fields. Wins over record_data. Answers { created, ids }. |
define_model
Scope: apps:write
Define/merge a data model (record type) into the app's schema. Data is stored as JSONB; no migration needed.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
model_key | string | yes | e.g. 'article'. |
label | string | ||
fields | object | yes | Map of field name → type ('text'|'number'|'json'|'uuid'|...). |
delete_app
Scope: apps:delete
PERMANENTLY delete an agent-authored Space App: uninstalls it (if published) and removes its code, data records, version history and change log. Cannot be undone — there is no trash. Requires the OPT-IN apps:delete permission, which is NOT part of default/full access; if you can see this tool, the owner explicitly granted it to this key. Prefer update/rollback over delete-and-recreate: deleting destroys user data and history. Pass the app's exact current name in confirm_app_name to confirm.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
confirm_app_name | string | yes | The app's exact current name — a mismatch aborts the deletion. |
delete_app_data_record
Scope: apps:write
Delete a record from a Space App's data store.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
record_id | string | yes |
edit_app_code
Scope: apps:write
PREFERRED way to fix/change an existing app: surgical find-and-replace edits inside ui_code, so you never resend the whole document for a small change (faster, cheaper, and immune to output truncation). Each edit's old_string must match the current code EXACTLY (including whitespace) and be unique unless replace_all. The patched result is validated like a full save (syntax + lint + auto-declared capabilities); a failed patch keeps the previous working code. Read the current code with get_app first. PUBLISHED apps: if this key has the apps Publish permission (apps:run — agent keys have it by default), the patched code goes LIVE immediately with a version snapshot for rollback; without it, edits stage as a pending draft only the space owner can publish. ALWAYS pass change_description.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
edits | object[] | yes | |
change_description | string | REQUIRED in practice: one-line summary of what you changed and why — the owner reads this in the app's change log before publishing your update. |
get_app
Scope: apps:read
Get a single app: its guide for agents first when it has one (guide — how this app expects to be worked in; follow it), then its schema — and its ui_code / app_files (for an app with a guide only with include_code: true). Read this before working in any app you were told to use.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
include_code | boolean | Only when you are changing the app itself: returns its ui_code and app_files even when it has a guide. |
get_app_data_record
Scope: apps:read
Get one Space App record by id (full record_data). The visitor field says whose it is: null = the space's own record, otherwise the person whose shared-app sandbox it lives in — treat theirs as personal data.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
record_id | string | yes |
get_app_logs
Scope: apps:read
Read an app's recent errors so you can diagnose and fix it after a test run: the latest uncaught runtime/render error (e.g. blank render) plus recent SDK-call failures (e.g. a denied capability or gateway error). Call this after a user opens the app if something looks wrong.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
limit | number |
get_app_pipeline_run
Scope: apps:read
Check a pipeline run by job_id: status, per-step results (including generated asset URLs), cost so far, and the error if a step failed.
| Parameter | Type | Required | Description |
|---|---|---|---|
job_id | string | yes |
get_app_sdk_reference
Scope: apps:read
Get the full window.wakato in-app SDK reference — every method an app's ui_code can call (data, gateway/AI, contacts, sms, messaging, social, assets, calendar, bank, etc.), response shapes, and which capability to declare for each. Call this BEFORE writing or updating an app's ui_code so you use real methods. Free.
get_app_share
Scope: apps:read
Get an app's active external share: full config, the share URL, and headline analytics (page views, unique visitors, total visits, visitor AI spend this month and all-time). Returns { share: null } if the app is not currently shared.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes |
get_app_version
Scope: apps:read
Get one snapshot from an app's version history, including its ui_code and schema — useful to diff against the current code when hunting a regression.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
version_number | number | yes |
grant_app_capabilities
Scope: apps:run
Approve (enable) an app's requested capabilities so it can use them at runtime — data access, AI models (gateway.*, billed to the space wallet), asset uploads, etc. Grants ONLY capabilities the app declared in required_capabilities (least-privilege). publish_app already auto-grants declared capabilities, so use this mainly to re-enable after a revoke or grant a specific subset. Requires apps:run.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
capabilities | string[] | Optional subset of declared capability keys to grant (e.g. ['gateway.llm','data.insert']). Omit to grant all declared capabilities. |
install_app_template
Scope: apps:write
Install an app from the Wakato library into this space as the space's own copy (empty, at the template's current version) — the way to get a folder back after it was deleted, or to set one up for the first time. If the app is one an agent works in, YOU become its worker unless another living agent already is; a folder you already work in is returned as it is. Requires apps:write.
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id | string | yes | From list_app_templates. |
introspect_capabilities
Scope: apps:read
Discover what AI models and services this space can use (and which are enabled vs available-but-off), plus the full list of app capability keys. Call this BEFORE building so you know what to declare and what the user may need to enable.
list_app_data_models
Scope: apps:read
List the data models a Space App actually has records for (model_key + record count). Counts split owner_count (the space's own records) from visitor_count (records made by people using the app through an external share). Use this to discover what data the app holds before querying.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes |
list_app_pipelines
Scope: apps:read
List the operations a Space App exposes to agents — its declared pipelines (name, inputs, steps) plus the data models they write. Call this BEFORE trying to do an app's job by hand: if the app declares a pipeline for it, running that pipeline reproduces the app's own prompts, model choices and record shapes, and the result appears in the app exactly as if a person had done it.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes |
list_app_templates
Scope: apps:read
The Wakato app library: ready-made apps a space can install as its own copy (Content Desk, …). Returns each template's id, name, description, whether an agent works in it (agent_run), whether it carries a guide for agents (has_guide) and, when this space already has it, the installed app's id. Install one with install_app_template.
list_app_versions
Scope: apps:read
List an app's published version history (every publish_app and rollback records a permanent snapshot). Returns version_number, note, created_at. Use get_app_version for a version's code, rollback_app to restore one.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
limit | number |
list_app_visitors
Scope: apps:read
Per-visitor analytics for an app's active external share: email (null for anonymous guests on open public shares), first/last seen, visit count, total time in app, and AI spend. Most recent first, up to 500.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes |
list_apps
Scope: apps:read
List platform-hosted Space Apps in this space (id, name, status, trust tier, granted capabilities). has_guide: true means the app carries a guide for agents — read it with get_app before you work in that app.
list_data_kinds
Scope: apps:read
The kinds of data Wakato apps pass to each other (hook, tip, mistake, number, story, quote, research, playbook, post, script, idea, contact, product) with each kind's fields, and which apps in this space receive or send which kinds. Read it before giving an app a way to RECEIVE data from another app or from Deep Market Research — it says exactly what to add to the app's schema.
list_my_spaces
Scope: apps:read
List the spaces this agent may work in, which one is its home (the space billed for the agent's own thinking), and what it is allowed to do in each. Pass a returned id as space_id on any tool to work in that space.
present_app
Scope: apps:read
Show a Space App live in your chat's panel (Apps & Pages tab). Call it when you start building or changing an app, or when the user asks to open/see one, so they can watch it live. UI-only signal — succeeds even if the panel is closed, and stores nothing.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes |
preview_app
Scope: apps:read
Static validation of an app: ui_code present, real JS syntax check of every <script> block, capabilities known + declared for every SDK call used, pipelines well-formed. Returns { ok, issues, warnings } — issues BLOCK publish_app. Free. For an actual execution test, use test_app.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes |
publish_app
Scope: apps:run
Publish an app FOR THE FIRST TIME: install it into the space so members can open it AND auto-grant the capabilities it declared so it's ready to use immediately (no separate owner approval step). Least-privilege: only declared capabilities are granted; gateway (AI model) usage bills the space wallet, and the owner can revoke any capability from the App Inspector. BLOCKS if validation fails (syntax errors, missing preact-ready guard, undeclared capabilities) — run test_app first so you publish code you have actually seen run. On an ALREADY-PUBLISHED app with a pending draft, this PROMOTES the draft live (update_app/edit_app_code already do this automatically when you hold this permission). Requires apps:run (Publish).
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes |
push_app_data_to_visitor
Scope: apps:write
Put records INTO one visitor's private copy of an externally shared app — the way to hand someone the work you did for them (research, drafts, a filled-in plan) so it appears inside the app they already use, in their own sandbox. Get visitor_id from list_app_visitors. Refused for revoked shares, reserved '_' collections, and collections the share marks read-only for visitors. The visitor's storage limit applies; if their sandbox is full the owner can raise it in the app's Share settings.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
visitor_id | string | yes | From list_app_visitors. |
model_key | string | yes | Must match a model the visitor's app can read. |
record | object | One record's data (matching the app's schema for that model). | |
records | object[] | Several records at once (max 200). Wins over record. |
query_app_data
Scope: apps:read
Read a Space App's stored records for one model (the rows the app's window.wakato.data lives on). Paginated, newest first. If the app is shared externally, results include BOTH the space's own records and each visitor's private sandbox — every record carries visitor: null means it is the space's own, otherwise it is that person's personal data inside the owner's app. Use visitor records to help the people using the app (answer them, fix their setup, send them work); do NOT publish, post, email or hand them to another agent unless the owner asked for exactly that. Narrow with data_scope:'owner' when you only want the space's own records, or visitor_id for one person.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
model_key | string | yes | From list_app_data_models / the app schema. |
limit | number | ||
offset | number | ||
data_scope | owner | visitors | all | Default 'all'. 'owner' = the space's own records only · 'visitors' = shared-app sandboxes only. | |
visitor_id | string | One visitor's sandbox only (from list_app_visitors). Wins over data_scope. | |
where | object | Only records whose fields hold these values, e.g. { "brief_id": "…" } or { "brief_id": "…", "status": "draft" }. The answer's total counts every match. | |
fields | string[] | Only these fields of each record, e.g. ["text", "views", "tier"] — read a big collection light, then open one record whole with get_app_data_record. | |
order_by | object | Order by one field instead of newest first, e.g. { "field": "views", "desc": true } or { "field": "said_by", "desc": true }. |
remove_app_from_chat
Scope: apps:run
Take an app out of a PM chat it was shared into (share_app_to_chat). The line already posted stays; the app stops opening from it. Other doors (link, community, profile, other chats) are untouched.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
kind | dm | group | yes | |
chat_id | string | yes |
research_ai_summary
Scope: apps:read
What people ask AI about a market research brief's market, and what the AIs answer, in totals: the questions (about how many times a month each — an estimate), who the AIs name most and in how many questions, the sites they quote most, in how many questions this offer is named, and what is still to note. For the "How AI answers this market" section and the playbooks.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
limit | number | How many questions to list, up to 60 (default 30). |
research_find_evidence
Scope: apps:read
Find the evidence saved on a market research brief, to write a section: by kind, platform and words in the quote or summary, loudest (most engagement) first, up to 80 at a time with offset.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
kind | pain | objection | competitor | pricing | channel | quote | belief | fear | desire | trend | demographic | feature_gap | tip | mistake | stat | story | ||
platform | string | One platform or source type (tiktok, reddit, trustpilot, web…). | |
text | string | Words that appear in the quote or summary. | |
limit | number | Up to 80. | |
offset | number |
research_finish
Scope: apps:write
Mark a market research brief done. It is checked first: every section written, the evidence behind each research section, the minimum searches on every platform, every source set aside with a reason (and no more than half of a platform's videos without a second look), and the playbooks (all seven, written from the finished sections, each citing what it stands on — unless the person asked for fewer) — if anything is missing it says every gap and nothing changes. A lane you really tried and that gave nothing may be skipped with the reason. Answers what the brief cost (cost_usd) — tell the person that number.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
skipped_lanes | object[] | Lanes searched at least once that truly gave nothing, with why. | |
playbooks | string[] | Only when the PERSON asked for fewer playbooks: the ones they want ([] = just the research, no playbooks). Leave it out for all seven. | |
playbooks_why | string | Required with fewer than all seven: what the person said. |
research_get_brief
Scope: apps:read
Where a market research brief stands: status and live line, sources per platform (and how many are still unread), evidence per kind, searches done per lane against the minimum, each section's status and evidence count, and everything still missing before research_finish will accept it.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes |
research_guide
Scope: apps:read
Start here before any business research or market research — the Deep Market Research app's own instructions: how to agree the angle with the person, open a research brief, search every platform, read the sources, save the evidence, write the 21 sections, finish, and write reports. Read it once per brief.
research_list_briefs
Scope: apps:read
List this space's market research briefs (Deep Market Research): title, status, the live line, how many sources and evidence items, sections written, and which agent is doing it.
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | Only briefs in this status (collecting, extracting, generating, synthesizing, done, error). |
research_list_themes
Scope: apps:read
The themes saved so far in a market research brief, with how many items each holds (and how many items still have none). Read it before saving, so the same point keeps the same wording and becomes one ranked card in the content bank.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
kind | string | Only this kind (tip, mistake, pain…). |
research_note_ai_answers
Scope: apps:write
Note what an AI's answer says, for a market research brief's AI sources (source types ai_question and ai_answer — read them first with research_read_sources): who it names (every brand, product or business it recommends, in its order), whether THIS offer is among them, the opening in one line (the room the answer leaves, or that it has none) and why people ask it. Up to 50 per call. Marks them read; the Content bank's "Asked to AI" shelf and the report's AI section draw from these notes.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
notes | object[] | yes |
research_playbook_material
Scope: apps:read
Everything one PLAYBOOK of a market research brief should be written from (once its 21 sections are written — the playbooks come before research_finish): what it must cover, the sections it stands on (their text), the positioning playbook, and its own pull from the sources — top videos with the words their creators open with, creators, hashtags, the competitor ads that have run longest, search keywords with volume and cost, real prices, one- and five-star reviews, objections, the people who posted the problem in public and where they talk. Every item carries its evidence_id / source_id to cite. Call it before research_write_report.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
kind | positioning-messaging | content-audience | gtm-build | sales-enablement | paid-acquisition | cold-outreach | market-strategy | yes |
research_read_section
Scope: apps:read
Read one written section of a market research in full (ideal-customer-profile, buying-journey, voice-of-customer, market-beliefs, hidden-fears, secret-desires, … — the slugs research_view lists).
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
slug | string | yes |
research_read_sources
Scope: apps:read
Read a market research brief's sources — title, link, author, platform, reach and the text (up to ~2,500 characters each, ~10,000 for a video: its caption then "What is said in the video:" and the transcript — ask for up to 3 source_ids to get a long transcript whole; thin web pages are fetched in full first) — up to 20 at a time, to pull the evidence out of them. unread_only gives the ones you have not saved evidence from yet.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
source_ids | string[] | Read these sources (up to 20). | |
platform | string | Only one platform or source type (tiktok, reddit, web, exa_web, review_trustpilot…). | |
unread_only | boolean | Only sources not read yet. | |
set_aside | boolean | Only sources you set aside (read, nothing saved), most-watched first — to look again. | |
limit | number | How many, up to 20. |
research_save_evidence
Scope: apps:write
Save the facts you pulled out of a market research brief's sources — up to 100 per call, each tied to its source_id: kind (pain, objection, competitor, pricing, channel, quote, belief, fear, desire, trend, demographic, feature_gap — and for the content bank: tip, mistake, stat, story), the EXACT quote when there is one (never paraphrased, never invented), your one-line summary, who said it, a THEME (the point in a few words — the same wording for the same point, see research_list_themes) and its USEFULNESS for content (1–5). Save everything usable in a source, not the best few: the content bank ranks it. The sources cited are marked read.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
items | object[] | yes |
research_search
Scope: apps:write
Run ONE paid search for a market research brief on one platform (lane) and keep every result in the brief as a source. Billed to the space's wallet. Lanes: web, web_deep (long reports and statistics), youtube_videos, youtube_shorts, tiktok, instagram, reddit, x, threads, linkedin, tiktok_ads, meta_ads, google_ads, ai_questions (real questions people ask ChatGPT and Google's AI answers, with about how many times a month — query = 1–3 words, "snack box + nurse" for both), ai_answers (ask ChatGPT, Gemini and Perplexity one question now — query = the question as a buyer would ask it), shopping (Google Shopping products), reviews_google (query = a business name and city), reviews_trustpilot (query = a company's domain). Use the buyer's own words and a DIFFERENT phrasing each time, from an angle of the brief's keyword plan — repeats do not count toward a lane's minimum. What a search brings is screened against the brief: plainly off-topic results are set aside and the answer says how many were on topic (rephrase when few were). Every on-topic video (YouTube, TikTok, Instagram, video ads) is transcribed as it lands, billed per video; a Google ads search brings its related keywords with volume and cost per click.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
lane | web | web_deep | youtube_videos | youtube_shorts | tiktok | instagram | reddit | x | threads | linkedin | tiktok_ads | meta_ads | google_ads | ai_questions | ai_answers | shopping | reviews_google | reviews_trustpilot | yes | |
query | string | yes | The words to search (a business name for reviews_google, a domain for reviews_trustpilot). |
limit | number | Results to ask for, up to 50 (each lane has a sensible default). | |
country | string | Search one other country this time (2-letter code or name) — default: the brief's region. Lanes that take a place: tiktok, youtube_*, tiktok_ads, meta_ads, google_ads, shopping, ai_questions, ai_answers. | |
angle | problem | outcome | product | competitors | buyer | fears | price | moments | yes | The keyword-plan angle this search comes from. |
recent | any | year | month | How recent: default the past year on Reddit and YouTube Shorts, any elsewhere; month narrows TikTok, YouTube and Reddit. |
research_send_to_app
Scope: apps:write
Send lines from a market research's content bank into an app in this space that receives them — hooks (by views), or the best-ranked tips, mistakes, numbers, stories or quotes (the buyers' pains, fears, objections…). Give evidence_ids / source_ids to send exactly those, or top to send the best N (default 20). The app must receive that kind (list_data_kinds, check_app_door).
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
kind | hook | tip | mistake | number | story | quote | yes | |
app_id | string | yes | |
top | integer | The best N by the content bank's ranking (when no ids are given). | |
evidence_ids | string[] | ||
source_ids | string[] | For hooks: the videos' source ids. |
research_set_keyword_plan
Scope: apps:write
Set or change the keyword plan of a market research brief: the angles every search comes from (problem, outcome, product, competitors, buyer, fears, price, moments), in the buyer's words. A brief needs one before its first search; research_start_brief takes it too.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
keyword_plan | object | yes | The angles you will search from, 2–12 phrases each in the BUYER's words; at least 5 angles, competitors named. |
research_set_progress
Scope: apps:write
Tell the person watching a market research brief what you are doing now — one plain line ("Reading TikTok — 64 sources so far") and, when it changes, the stage: collecting, extracting, generating or synthesizing.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
line | string | yes | |
stage | collecting | extracting | generating | synthesizing | ||
progress_pct | number | 0–99. |
research_set_themes
Scope: apps:write
Give saved items of a market research brief their theme and usefulness (1–5) — items saved before themes existed, or a better wording that joins two cards into one. Up to 200 per call.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
items | object[] | yes |
research_skip_sources
Scope: apps:write
Set aside market research sources you read that hold nothing worth saving (boilerplate, off-topic, duplicates, music with no words), with WHY in one line — so they stop coming back as unread, and the person sees why. off_topic also hides them from the brief's sources and numbers.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
source_ids | string[] | yes | |
why | string | yes | One line, for all of these: what they hold and why nothing in them is worth saving. |
off_topic | boolean | They are not about this market at all. |
research_start_brief
Scope: apps:write
Open a new market research brief (Deep Market Research) once the person has agreed the angle — WHO it is for and WHAT is sold. You then do the research yourself: search, read, save evidence, write the sections, finish. Answers the brief_id, the 21 sections and the minimum searches per platform. Read research_guide first.
| Parameter | Type | Required | Description |
|---|---|---|---|
title | string | yes | The one line agreed with the person, e.g. "At-home cold plunge for CrossFit athletes 25–40 in the US". |
angle | object | yes | The market angle the whole brief is aimed at. |
idea_text | string | yes | The business idea in the person's words. |
region | string | The ONE country the buyers are in — a 2-letter code (US, FR, GB) or its name. TikTok, YouTube, the ad libraries, Google keyword numbers, Google Shopping and the AI searches all look there. A group of countries ("Europe") is not one place: those searches then look in the US. | |
audience_type | b2b | b2c | either | ||
language | string | Language of the brief (default en). | |
depth | standard | deep | standard ≈ 150–250 sources, deep ≈ 300–500 (default deep). | |
keyword_plan | object | yes | The angles you will search from, 2–12 phrases each in the BUYER's words; at least 5 angles, competitors named. |
playbooks | string[] | Only when the PERSON asked for fewer playbooks: the ones they want ([] = just the research, no playbooks). Leave it out for all seven. | |
playbooks_why | string | Required with fewer than all seven: what the person said. | |
reviewed_skips | object[] | Only when more than half of a platform's videos gave nothing and you looked again at the most-watched: the platform and what they really hold. |
research_view
Scope: apps:read
Read a finished market research the way an app that LINKS it does (Content Desk): the posts behind its hooks with views, likes, comments, shares, the creator's followers, seconds and a breakout score (views ÷ followers; tier breakout, did_well, average or flopped — flopped ones kept on purpose), the themes people say (how many voices, how many platforms, a real quote), what people ask AI and what the AIs answer, and the report's sections. Open one post's whole transcript with research_read_sources (source_ids) and a whole section with research_read_section.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes |
research_write_report
Scope: apps:write
Write one PLAYBOOK of a market research brief, once its sections are written and before research_finish (people see these as playbooks; the tool keeps its old name): positioning-messaging (write it first — the others use it), content-audience (Content playbook), gtm-build (Go-to-market plan), sales-enablement (Sales playbook), paid-acquisition (Paid ads playbook), cold-outreach (Cold outreach playbook), market-strategy (Business case). Write it from research_playbook_material, in markdown, and cite what you used. Writing the same kind again replaces it.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
kind | positioning-messaging | content-audience | gtm-build | sales-enablement | paid-acquisition | market-strategy | cold-outreach | yes | |
title | string | Optional; each kind has its own title. | |
content_md | string | yes | |
source_section_slugs | string[] | The sections it draws on. | |
evidence_ids | string[] | The evidence it uses (from research_playbook_material or research_find_evidence). | |
source_ids | string[] | The sources it names — videos, ads, reviews, posts. |
research_write_section
Scope: apps:write
Write (or rewrite) one section of a market research brief in markdown, citing the evidence and sources it stands on — the brief shows them beside it. Sections outside Overview and Strategic Positioning need at least 8 evidence items from 3 different sources (Voice of Customer: 20 from 6). Answers what the section still lacks.
| Parameter | Type | Required | Description |
|---|---|---|---|
brief_id | string | yes | |
slug | string | yes | The section, e.g. market-sizing, voice-of-customer, executive-summary. |
content_md | string | yes | |
evidence_ids | string[] | Every evidence item the section uses. | |
source_ids | string[] | Sources used directly (the sources behind the evidence count already). | |
confidence | high | med | low | ||
data | object | Optional structured payload (a table's rows, a list) the page can draw. |
revoke_app_capabilities
Scope: apps:run
Revoke an app's granted capabilities so it can no longer use them at runtime. Omit capabilities to revoke everything, or pass specific keys to revoke a subset. Requires apps:run.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
capabilities | string[] | Optional subset of capability keys to revoke. Omit to revoke all. |
revoke_app_share
Scope: apps:run
Turn off an app's external sharing: the /a/<token> link stops working IMMEDIATELY and every visitor session dies with it. Visitor data and analytics are kept. Sharing again later (share_app) mints a NEW link — the old URL stays dead.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes |
rollback_app
Scope: apps:write
EMERGENCY RESTORE: set the app's live code/schema back to a published version (from list_app_versions) — use this FIRST when a published app is crashing for users, then fix calmly and re-publish. Records the restore as a new version (history stays append-only) and clears the crash latch.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
version_number | number | yes |
run_app_operation
Scope: apps:write
Perform one of a Space App's own OPERATIONS — the things its buttons do, for apps whose work lives in a dedicated function rather than a pipeline. Discover the list (and which ops publish) with list_app_pipelines. No Wakato app registers operations today; list_app_pipelines says when one does. Same function the app's own UI calls, so an agent and a person operating the app are one code path.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
op | string | yes | Operation name from list_app_pipelines.operations. |
pilot_id | string | Which project inside the app, when it has several (a record id). | |
record_ids | string[] | Records to act on. | |
record_id | string | ||
count | number | How many items an op that makes a batch should make. | |
image_url | string | An https image the op reads, when it takes one. | |
label | string | A name for whatever the op creates — e.g. the name of a derived template. | |
dry_run | boolean | Validate without writing or publishing. |
run_app_pipeline
Scope: apps:write
Run one of a Space App's declared pipelines with inputs — the agent equivalent of a person using the app. Executes server-side through the API Gateway (billed to the space wallet, attributed to the app) under the app's own capability consent. Returns a job_id immediately; image and video steps take 1–5 minutes. Poll get_app_pipeline_run. Records land live in the app, so the user sees them without refreshing. Pass dry_run to validate the flow without spending.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
pipeline | string | yes | Pipeline name from list_app_pipelines. |
inputs | object | Values for the pipeline's declared inputs. | |
dry_run | boolean | Validate and render the steps without calling providers or writing records. |
send_records_to_app
Scope: apps:write
Send records of one app of this space into another app of this space — a copy of the same app takes them as they are; any other app takes them when it RECEIVES the kind the first app SENDS for that collection (its schema's sends/receives doors; check_app_door). The records stay where they were; the new ones say where they came from. E.g. qualified leads from a lead finder into an outreach app.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | The app the records are in. |
model | string | yes | Their collection (query_app_data shows the record ids). |
ids | string[] | yes | The records to send (up to 2000). |
into_app_id | string | yes | The app they go into. |
kind | string | Only when the app sends that collection as more than one kind. |
send_to_person
Scope: apps:write
Send something to a person — anyone on Wakato (to_user_id) or any email (to_email: someone not on Wakato gets an email and finds it when they join). They choose where it goes and get their own copy. what = research_copy (a whole finished research, brief_id), research_lines (content-bank lines: brief_id, kind, evidence_ids / source_ids) or app_records (an app's records: app_id, model, ids; include_app brings the app to someone who lacks it). Always confirmed by the person you work for first — it sends their data out in their name.
| Parameter | Type | Required | Description |
|---|---|---|---|
what | research_copy | research_lines | app_records | yes | |
to_user_id | string | Someone on Wakato (their account id). | |
to_email | string | Or an email address. | |
note | string | A line for them (optional). | |
brief_id | string | ||
kind | hook | tip | mistake | number | story | quote | ||
evidence_ids | string[] | ||
source_ids | string[] | ||
app_id | string | ||
model | string | ||
ids | string[] | ||
include_app | boolean | Bring the app to someone who doesn't have it (default true). |
share_app
Scope: apps:run
Share a platform-hosted app with people OUTSIDE the space via an external link (https://wakato.io/a/<token>). Creates the app's single active share, or updates it if one exists (settings apply live). WHERE the app is published decides who gets in: published into a community = its approved members only; published onto a public Wakato Profile = anyone may LOOK (read-only) and a signed-in Wakato account may use it; a bare link nobody published = the access_level/email settings below. access_level: 'link' = anyone with the link, email-verified · 'invite' = only invited_emails (requires at least one; pass keep_invited_emails to update other settings without resending the list) · 'public' = open link where require_email:false may relax the email gate. visitors_can_use:false makes the app view-only for everyone but the owner. AI for visitors is OFF by default; ai_enabled:true REQUIRES visitor_daily_cap AND share_monthly_cap above $0 — visitor AI usage bills the SPACE wallet, so confirm budgets with the owner before enabling. data_mode: 'isolated' (default — each visitor gets a private data sandbox) or 'shared' (signed-in visitors work in the space's shared app data; anonymous viewers never see it); shared_read_models optionally exposes listed models read-only in isolated mode. Returns { share, share_url } — give share_url to the user. Requires the apps Publish permission.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
access_level | link | invite | public | Default 'link'. | |
require_email | boolean | Only relaxable on 'public' shares; link/invite always verify email. | |
invited_emails | string[] | Allowlist for 'invite' shares (max 500). Replaces the existing list unless keep_invited_emails. | |
keep_invited_emails | boolean | Keep the share's current invite list instead of replacing it. | |
visitors_can_use | boolean | Default true. False = view-only: nobody but the owner can save anything or run AI. Anonymous viewers are read-only regardless of this. | |
ai_enabled | boolean | Let visitors use the app's AI features, billed to the space wallet. Requires both caps > 0, and visitors_can_use. | |
visitor_daily_cap | number | Max $ of AI per visitor per day (default 1, max 1000). | |
share_monthly_cap | number | Max $ of AI across ALL visitors per month (default 20, max 100000). | |
data_mode | isolated | shared | Default 'isolated'. | |
shared_read_models | string[] | Model keys visitors may READ from the shared pool while in isolated mode (max 50). | |
visitor_storage_cap_bytes | number | Storage ceiling per visitor in bytes (default 25MB). Visitor data lives in this space and counts toward the owner's account storage. | |
share_storage_cap_bytes | number | Storage ceiling for ALL visitor data on this share, in bytes (default 2GB). |
share_app_to_chat
Scope: apps:run
Put an app in a Wakato PM chat — a DM or a group — so the people in it can open it right there, as YOUR space's app on your space's wallet. Nothing is copied into anyone's space; it is a door on the app's share, and being in the chat is what lets someone in. This is how a game for people to play together is delivered: share it into their group with mode 'together' and everyone in the group writes to ONE pool (the same records, live — see the Multiplayer recipe in get_app_sdk_reference). mode: 'own' = each person gets their own copy of the data · 'watch' = everyone sees your records, nobody can change them · 'together' = everyone uses the app in one shared pool. Paid services (AI models, image/speech generation) are OFF for the chat unless ai_enabled with a visitor_daily_cap — they bill the space wallet. You must be IN the chat: chat_id is the conversation or group you are talking in (your PM context gives it to you). The first share posts a line in the chat as you; calling again only changes the terms. Returns { placement, share_token, message_id, new_door }.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
kind | dm | group | yes | 'dm' for a one-to-one conversation, 'group' for a group. |
chat_id | string | yes | The wakato_pm_conversations id (dm) or wakato_pm_groups id (group). |
mode | own | watch | together | Default: what the app's share already says (own copy unless changed). Use 'together' for a game people play with each other. | |
ai_enabled | boolean | Let people in this chat use the app's paid services, billed to the space wallet. Requires visitor_daily_cap > 0 and a mode that lets them use the app. | |
visitor_daily_cap | number | Max $ of paid services per person per the app's allowance period (default 1). | |
allow_copy | boolean | Let people in this chat take their own copy of the app into a space of theirs. | |
note | string | A sentence to go with the line in the chat ('first to 100 wins'). |
test_app
Scope: apps:read
REALLY RUN the app before publishing: mints a short-lived test URL that renders the app exactly like production (same framework, same sandbox CSP) but answers all window.wakato.* SDK calls with harmless test-mode mocks (no wallet charges, no real data). Open the URL in headless Chrome on your machine and read the verdict: <title> becomes WAKATO_TEST_PASS/WAKATO_TEST_FAIL and <script id="wakato_test_results"> holds JSON with runtime_errors, sdk_calls and a render report. ALWAYS run this after saving ui_code and fix failures before publish_app. Free.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
ttl_seconds | number | Token lifetime in seconds (60–3600, default 900). | |
steps | object[] | Optional interaction script executed after first render (max 30) — exercise flows, not just the first paint. Each: { action: 'click'|'type'|'expect_text'|'expect_selector'|'keydown'|'keyup'|'pointerdown'|'pointerup'|'pointermove'|'wait'|'expect_game_state', selector?, text?, key?, code?, x?, y?, duration_ms?, field?, value?, comparison? }. | |
fixtures | — | Data for wakato.data.query mocks: 'auto' (default — sample records generated from data_models, tests the POPULATED UI), 'none' (empty-state test), or { model_key: [records] } (keep small, ~6KB max). |
update_app
Scope: apps:write
Update an agent-authored app's ui_code, app_files, schema or metadata. STANDALONE RULE applies: core function via wakato.gateway.* in-app; machine-dependent work declared in app_schema.agent_features and queued via wakato.agent.requestWork — never a silent records-viewer for work you do on your machine. ui_code is VALIDATED on save (real JS syntax check + runtime-fatal lint); a rejected update keeps the previous working code in place. PUBLISHED apps: if this key has the apps Publish permission (apps:run — agent keys have it by default), your change goes LIVE immediately with a version snapshot for rollback; without it, the change is staged as a pending draft only the space owner can publish. ALWAYS pass change_description (one line, owner-facing). After a successful update, run test_app before telling the user it's ready.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
name | string | ||
description | string | ||
icon | string | ||
color | string | ||
ui_code | string | Full HTML/JS. Uses the window.wakato.* SDK — see get_app_sdk_reference. | |
app_files | object | Map of filename → contents for multi-file apps. | |
app_schema | object | ||
change_description | string | REQUIRED in practice: one-line summary of what you changed and why — the owner reads this in the app's change log before publishing your update. | |
agent_guide | string | Optional guide for agents: plain text (up to 20,000 characters) on how to work in THIS app, returned first by get_app to any agent that opens it. Write one when the app is meant for agents to work in: what it is for, how to start (which records to create first), what each model/section means and what goes in it, how to read the person's decisions (what they approve, pick, note), which buttons send a message to the agent, and what never to do. Leave it out for an app people use on their own. Pass "" to remove it. Applies live at once (it is text, not code). |
update_app_data_record
Scope: apps:write
Update a Space App record. record_data is shallow-merged into the existing record by default; pass replace:true to overwrite it wholesale.
| Parameter | Type | Required | Description |
|---|---|---|---|
app_id | string | yes | |
record_id | string | yes | |
record_data | object | yes | |
replace | boolean | Replace record_data instead of merging. |