Ninjo
Manage AI engagement agents
- Category
- AI
- Primary Subcategory
- AI Agent Builders & Deployment Platforms
Integration details
Description
Ninjo helps operators run their AI engagement agents in plain language: diagnose an agent's setup and get prioritized fixes, review the conversations it handled, edit prompts and triggers, audit the contact limits, follow-up workflows and notifications wired around it, and segment the contact directory by custom-property values.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- AI Agent Builders & Deployment Platforms
- Secondary Subcategories
- None listed
- Brand
- Ninjō
- Access
- Account required
- First tracked
- 2026-07-04
- Tool count
- 115
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
Get alerts for Ninjo
Get updates when Ninjo’s Discoverability Score or category rank changes.
ChatGPT Plugin Discovery Score
ChatGPT Plugin discovery is coming soon
ChatGPT can surface a Plugin when it matches a user's request.Your Plugin Discovery Score measures how often yours appears.
No spam. Unsubscribe any time.
What discovery looks like

Competing in ChatGPT AI Agent Builders & Deployment Platforms
View Category115 tools agents can invoke
Queue one or more allowed customer phone numbers for Cortex WhatsApp direct routing. The gateway forwards the request to mk1-tasks, which normalizes the numbers, checks whether any number already belongs to another influencer, and enqueues the association task when there are no conflicts. Returns { status: "queued", taskId } on success or { error: "phone_number_conflict", requested_influencer_id, conflicts: [...] } when a number is already mapped elsewhere.
associate_whatsapp_direct_numbers
Queue mk1-tasks bootstrap for the influencer's Discord operator channel. This creates or repairs the stored Discord mapping asynchronously through mk1-tasks. The downstream bootstrap creates the role, private channel, and permanent invite when needed. Returns { status: "queued", taskId } on success.
bootstrap_discord_channel
Switch an existing GoHighLevel WhatsApp channel between GoHighLevel's official WhatsApp and an external provider (a WhatsApp QR/app integration registered inside GHL). Use this when create_messaging_channel was called with the wrong third_party_whatsapp value — the symptom is that inbound messages arrive but Ninjo's replies never send. The channel cannot simply be recreated (one WhatsApp channel per account), which is why this exists. Only applies to GoHighLevel WHATSAPP channels; Kommo and every other channel type are rejected. Returns { channel, third_party }. Check third_party, not channel: the flag lives on the connected account, so channel is byte-identical before and after — third_party is read back from the account after the write and is the only confirmation the flip landed.
set_messaging_channel_whatsapp_provider
Mint a one-time magic-link the account owner opens in a browser to authorize an integration: Instagram / Facebook, a CRM ('gohighlevel_crm', 'hubspot_crm', 'kommo_crm'), booking ('gohighlevel_booking', 'calendly') or the Google Calendar the agent books into ('google_calendar'). Connecting requires human OAuth consent at the provider — this tool cannot complete it. Hand the returned URL to the user and ask them to open it and authorize; do NOT open it yourself. The link needs no prior Studio login (it mints a short-lived, influencer-bound session on redeem), is single-use and expires after a few minutes. NEVER ask the user for an API key, token or password for these — none of them is used by this flow (in particular a GoHighLevel private-integration token is NOT needed). GoHighLevel has TWO separate integrations: 'gohighlevel_crm' (contact/opportunity sync, Studio screen automation/crm-sync) and 'gohighlevel_booking' (call tracking, Studio screen integrations/gohighlevel). Ask which one the user means instead of guessing. After the user authorizes, poll get_connection_status. Booking is NOT finished at that point — it reports pending_step:"select_calendars", so continue with list_booking_calendars + set_booking_calendars. CRM needs nothing more (pipelines/stages matter only when wiring a property action). Google Calendar ('google_calendar') is NOT booking tracking and has no calendars to select — never call list_booking_calendars / set_booking_calendars for it. It is the calendar the agent itself reads and books into (v5 agents only), one per workspace. After consent get_connection_status reports pending_step:"enable_for_agent_in_studio": finish it with set_google_calendar_agent for each agent that should book (the user can also do it in Studio at /studio/{influencer_id}/integrations/google-calendar). Then have them review the booking rules on that screen — left unset they default to Monday–Friday 9:00–18:00, 30-minute slots and a video call, which is wrong for most in-person businesses. ManyChat is not supported here: it has no OAuth. Send the user to /studio/{influencer_id}/integrations/manychat, where THEY fill in four things: the channel (WhatsApp / Instagram / Facebook), the API key, a shared webhook secret, and then they must COPY the webhook URL that screen shows them and paste it into ManyChat itself. Never ask for or echo the API key. Warn them that the last step happens inside ManyChat, so Ninjo cannot confirm it — get_connection_status only sees the first three. Returns { provider, url, expires_at }.
create_connect_link
Create a new Ninjo agent with its initial system prompt. Creates the Agent, AgentConfig, and first AgentPromptVersion atomically, with safe humanization defaults (message chunking on, MEDIUM delay split, 2–6s response delay — all overridable). Returns { agent_id, agent_config_id, prompt_version_id, completeness }. completeness is the deterministic build/wiring audit of the new agent: a fresh agent reports critical gaps by design (no terminal stop, not linked to a connected account) — wire them with scaffold_agent_activation before treating it as done.
create_agent
Upload a context document for a Ninjo agent. If file_base64 is provided, uploads to S3 at agents/{influencer_id}/context/{uuid}/{file_name}. Returns the created document row.
create_document
Step 1 of reporting feedback (optional, only when a log excerpt is needed to reproduce the problem). Returns a short-lived presigned S3 PUT URL + s3_key. Write ONLY the tool calls and error responses involved in the failing task to a file and PUT it to upload_url (no special headers needed) — never the user's messages or the rest of the chat; the bytes never pass through the tool-call payload or model context. Then call report_feedback with the returned s3_key as session_s3_key. Returns { upload_url, s3_key }.
create_feedback_upload_url
Step 1 of uploading an agent-sendable audio/image clip. Returns a presigned S3 PUT URL + s3_key — the file bytes are NOT sent through this tool. AUDIO must be M4A/AAC (MP3 rejected); IMAGE must be JPG/PNG/GIF. Next: PUT the file to upload_url with the same Content-Type header (e.g. `curl -T file.m4a -H 'Content-Type: audio/mp4' '<upload_url>'`), then call register_creator_resource with the s3_key. Returns { upload_url, s3_key }.
create_resource_upload_url
Create a new Cortex thread (conversation between the influencer and their AI agent). Returns the new conversation object with id, title, status, created_at. Uses JWT for RLS when available; with API key/admin, pass influencer_id.
create_thread
Create a trigger for a Ninjo agent. `type` selects the variant and which fields apply: • keywords — DM keyword trigger: keyword (required), match_mode (KEYWORD_ONLY|ANYWHERE), allow_typo. • all-messages — fires on every DM or comment: keyword must be ALL_DM or ALL_COMMENTS; prompt_evaluator optional. • comments — comment keyword trigger: keyword (required), match_mode, allow_typo, responses (public reply templates). • ads — ad referral trigger: ad_id (required). • outgoing-messages — fires on an outgoing message keyword: keyword (required), assign_unpaused. • instagram-story — story reply trigger: story_id (required), story_created_at. Returns { trigger } — the created trigger row.
create_trigger
Create a new WhatsApp message template and submit it to Meta for review (via mk1-chat). This SENDS NOTHING — it registers a template that can be broadcast later, once Meta approves it. Creation is asynchronous, so plan for the wait: 1. Call this tool. It returns { templateId, status } — status is normally PENDING, which means NOT usable yet. 2. Meta review usually takes minutes but can take up to 24h. Poll list_whatsapp_templates with includeAllStatuses:true and find this template by name/templateId: watch its status go PENDING → APPROVED. (The default listing shows APPROVED only, so on that path the template simply appears once approved — but includeAllStatuses:true lets you see it the whole time, including while PENDING.) 3. If it comes back REJECTED, the same includeAllStatuses:true listing carries its rejectedReason (why Meta rejected it) — no need to wait for Meta's email. Fix the wording that reason points at and create it again under a NEW name (a rejected name stays taken). 4. Once APPROVED, broadcast it the normal way: preview_whatsapp_template_recipients → confirm with the user → send_whatsapp_template. headerType decides which header field travels with it, and the two must agree: TEXT needs headerText, IMAGE needs headerImageUrl, the default NONE takes neither. A mismatch (an image URL on a NONE/TEXT header, a headline on a NONE/IMAGE one) is refused here before the call leaves, because headerType is what builds the template — a stray headerImageUrl would otherwise be dropped and the template created with no picture at all. For an IMAGE header, the headerImageUrl passed here is the sample Meta reviews. When you broadcast, pass the SAME headerImageUrl to send_whatsapp_template — that is what the contacts actually receive. A template lives inside one WhatsApp Business Account, so pass fromWhatsAppAccountId (from list_whatsapp_templates) when the influencer has more than one number connected, and send it later from that same account. Returns { ok, influencerId, templateId, status, name, languageCode, category }.
create_whatsapp_template
Permanently delete a Ninjo agent and all its associated data (triggers, prompt versions, documents, workflow relations, config). Cannot delete agents with active conversations — will return an error with the count. Returns { success: true }.
delete_agent
Delete a contact limit by id. Returns { success: true }.
delete_contact_limit
Delete a creator resource (removes the S3 object and the DB row). Returns { deleted, resource_id }.
delete_creator_resource
Delete a custom notification by id. Returns { success: true }.
delete_custom_notification
Delete a custom property by id. Returns { success: true }.
delete_custom_property
Delete a context document from a Ninjo agent. If the document has an S3 file_key, deletes it from S3 as well. Returns { success: true }.
delete_document
Delete a notification destination by id. Returns { success: true }.
delete_notification_destination
Delete a property action by id. Its subtype row (http / crm_*) is removed too. Returns { success: true }.
delete_property_action
Delete a Cortex thread and all its messages.
delete_thread
Delete a trigger by ID and type. type must be one of: keywords, all-messages, comments, ads, outgoing-messages, instagram-story. Cascades to trigger_negative_config if present. Returns { success: true }.
delete_trigger
Remove the negative config from a trigger. The trigger itself is not affected.
delete_trigger_negative_config
Delete a WhatsApp template definition by id (via mk1-chat). Refused with 409 if any notification destination still references it (detach or delete those first) — the definition is never silently orphaned. Returns { ok, influencerId, id }.
delete_whatsapp_template_definition
Delete a workflow by id. Returns { success: true }.
delete_workflow
Deploy the Cortex SDK (system.md + the 8 v5Config fields) to a Ninjo agent in one correct-by-construction call. Bakes the multi-step deploy the cortex skills enforce but the raw tools don't: (1) update the prompt column if `system` changed, (2) merge changed v5Config fields, (3) re-sync trigger_keywords whenever `keywords` is provided — so keyword changes are always dual-written (v5Config context AND what actually fires) and `system` never lands in v5Config. Diffs each provided field against the live config and only calls what changed; omitted fields are left untouched (PATCH semantics — there is no set-to-null). Then re-fetches and verifies (version bumped, fields match, no v5Config↔trigger_keywords drift). On verified=false or partial=true the deploy did NOT fully succeed: pass rollback_version_id to restore_prompt_version to revert both prompt and config. Returns the deploy report. IMPORTANT: this ships the agent's MESSAGES only (prompt + v5Config). It does NOT create the contact limits, custom notifications, or follow-up workflows that turn a prompt into a working agent — build those separately (upsert_contact_limit / upsert_custom_notification / upsert_workflow), gated on your custom properties. verified=true means the messages are live, not that the system is complete. The result also carries a `completeness` report (the same deterministic build/wiring audit as diagnose_agent mode=quick) run AFTER the deploy — resolve its critical/warn findings (or run scaffold_agent_activation) before treating the agent as done.
deploy_agent_sdk
Audit a live agent and return ranked defects, each with the exact fix tool. An agent is a SYSTEM, not a prompt: this is the "definition of done" as code. mode="quick" (default) — DETERMINISTIC tier only. Free, fast, reproducible: run it after every iterate. Service-role checks: no terminal contact limit, an active agent not linked to a connected account, ungated follow-ups, string-typed gating properties, hand-made properties duplicating an auto one (e.g. agendo_llamada ↔ call_booked), inert properties, missing conversion notification, robotic cadence (humanization off), v5Config↔trigger_keywords drift, and a prompt that names tools the agent does not have (the model narrates the call and confirms results that never happened). score/complete come from this tier. mode="full" — also runs two LLM-graded tiers (costs model calls — run pre-deploy or periodically, NOT every iteration): - behavioral: samples recent low-quality conversations (bad/stuck/low-happy) and grades them server-side — filter leak, NO_RESPONSE paraphrase, reasoning leak, premature booking. Needs a JWT-scoped token. Returns the sampled transcripts too. - prompt_audit: grades the deployed SDK (system.md + v5Config) against the best-practices rubric BP-2…BP-10 (fetched live from the wiki) — contradictions, example coverage, unguarded actions, voice drift, stale CTAs. Returns { agent_id, checked_at, mode, score (0–100, deterministic), complete, findings, behavioral, prompt_audit }. Resolve every critical/warn finding (across all tiers) before treating the agent as done.
diagnose_agent
Pause or resume a GoHighLevel / Kommo messaging channel without deleting it. Reversible; deleting a channel is not exposed here (do that in Studio). A channel is created already enabled, so there is NO need to call this after create_messaging_channel — use it to pause a channel while the user reconfigures something in the CRM, and to turn it back on. Get sync_connection_id from list_crm_connections (or list_agent_channels), picking a row whose event_name contains '.messaging.'. A row with a provider and no messaging event_name is the CRM SYNC connection, not a channel — this tool refuses those, since pausing it would stop contact sync for the whole account. Returns { channel }.
set_messaging_channel_enabled
Generate synthetic conversations for an agent by invoking the replicant Lambda. Two mutually-exclusive modes: pass `personas` for AI-simulated leads (user generated by an LLM), or pass `scripted_scenarios` to replay fixed user messages with no user-side inference (only the agent responds). Fan-out across the chosen items and return conversations in both structured and markdown formats. Returns { conversations, test_run_ids, lambda_invocations, lambda_errors, conversations_fetched, conversations_filtered, elapsed_seconds, warning }. `min_turns` defaults to 1 in scripted mode and 3 with personas; `warning` is non-null when every fetched conversation was dropped by min_turns (returned 0), suggesting a lower min_turns. influencer_id is inferred from the JWT when using an influencer-scoped token — only required when using admin or API key auth.
generate_synthetic_conversations
Report, per integration, whether it is authorized AND whether it is actually finished: Instagram, Facebook, the CRMs ('gohighlevel_crm', 'hubspot_crm', 'kommo_crm'), booking ('gohighlevel_booking', 'calendly'), 'google_calendar' and 'manychat'. Use this to poll after handing the owner a connect link, and to verify setup instead of asking the user whether it worked. Read setup_complete, not connected. oauth_ok:true with setup_complete:false is a real state — booking is fail-closed, so an authorized calendar account with nothing selected tracks zero bookings. pending_step says what to do next: "select_calendars" → set_booking_calendars; "paste_api_key_in_studio" → send the user to /studio/{influencer_id}/integrations/manychat to set the channel AND the API key (never ask for the key); "authorize_with_connect_link"/"reconnect" → create_connect_link; "enable_for_agent_in_studio" (Google Calendar) → set_google_calendar_agent, which finishes it without leaving the chat. For 'manychat', setup_complete:true means everything Ninjo can SEE is configured (channel + key). It cannot see whether the user pasted Ninjo's webhook URL into ManyChat, which is what makes messages actually arrive — so remind them of that step rather than declaring the integration live. Returns { influencer_id, channels: { <provider>: { connected, invalid_token, oauth_ok, setup_complete, pending_step, name } } }. Only requested channels are present (pass provider to narrow).
get_connection_status
Get the full configuration snapshot for a Ninjo agent: agent metadata, system prompt, and AgentConfig settings. Requires an influencer-scoped JWT. Returns { agent, config }.
get_agent_config
Fetch a windowed operational snapshot for an agent. Every section honors the `days` lookback (default 7). Sections (pass `sections` to fetch only what you need): - volume: new conversations / qualified leads / bookings sent over the window, plus a last-24h line - funnel: the influencer's configured funnel stages with conversation counts and conversion rates between consecutive stages (labelled with their own step names) - sources: per-source (Organic DM / Story Reply / Ad title) conversion performance - objections: stalled leads (funnel 1–3, quiet >72h) grouped by objection (MONEY/TRUST/TIMING/PRIORITY/UNKNOWN); null when the influencer has no objection properties configured Sections are computed independently: a slow or failing section comes back null with an entry in `warnings` — the rest of the report still arrives. `qualification.definition` states what "qualified" means in these numbers. To COMPARE several agents, prefer get_agent_metrics (one call, one row per influencer) over calling this tool per influencer. influencer_id is inferred from the JWT when using an influencer-scoped token (CUID like "cm…", not a username).
get_agent_insights
Calculate performance metrics for one or all agents. Includes volume (new_conversations, qualified_leads), engagement, funnel, lead score, booking rates, happy path, nurturing quality, monotonicity of funnel progression, and relative risk scores (z-scores). This is the tool for COMPARING agents: multi-influencer tokens that omit influencer_id (on an unscoped connection) get one row per authorized influencer in a single call — do not loop get_agent_insights per influencer. Returns { days, min_leads, agents: [{ influencer_id, influencer_username, leads, new_conversations, qualified_leads, avg_engagement_score, avg_funnel, avg_lead_score, funnel_to_lead_score_ratio, bookings_sent, booking_send_rate, call_booked_observed_leads, calls_booked, call_book_rate_total, call_book_rate_per_lead_observed, call_book_rate_per_booking_observed, pct_calls_booked_low_lead_score, avg_happy_path_score, avg_nurturing_score, pct_happy_lt_60, pct_nurture_lt_60, pct_lead_score_eq_1, pct_funnel_ge_4, premature_rate_refined, stages_compared, monotonic_violations, worst_drop, lead_score_monotonic_non_decreasing, risk_raw, risk_score_0_100 }] }.
get_agent_metrics
Everything the platform knows about ONE contact: native fields, the value of every custom property defined on the account, and the contact's conversations. This is the tool for "why did nothing happen for this person" — follow-ups, contact limits and notifications all gate on custom-property values, and this is the only way to read them for a given contact. Identify the contact with EXACTLY ONE of: contact_id (from search_contacts), whatsapp_number, instagram_username, email, phone. Passing two is rejected rather than silently AND-ed. If an identifier matches more than one contact row (which happens after a partial merge), the call fails with the count and asks you to use contact_id — it never picks one for you. READ is_set BEFORE DRAWING ANY CONCLUSION. Every property the influencer defines comes back, including ones this contact has never been given: - is_set: true → value holds the stored value (typed: boolean, number, option text, or string). This is what the automations see. - is_set: false → the evaluator has NEVER written this property for this contact, and value is null. That is NOT "false" and NOT "empty". A contact limit gated on compra_realizada behaves the same whether the property is false or unset, but the first means the evaluator ran and said no, and the second means it never ran — opposite fixes. Custom properties are written by the post-hoc evaluator agent, never by the conversational agent, so a wrong value is an evaluator question, not a prompt question. conversations lists the contact's conversations (newest first, up to 20) with conversation_id for get_conversation_messages / get_conversation_decisions, plus agent_conversation so you can see at a glance whether an agent was ever attached. Returns { contact_id, first_name, last_name, email, phone_number, whatsapp_number, is_whatsapp_subscribed, instagram_username, picture_url, created_at, properties: [{ codename, label, type, is_set, value, selected_options, updated_at }], properties_set_count, conversations: [{ conversation_id, type, agent_conversation, agent_id, last_message_at }] }.
get_contact
Fetch context data required to configure contact limits: available agents and custom properties with options. Returns { agents, customProperties }.
get_contact_limits_context
Explain why a lead saw no reply. Returns the platform's own recorded decisions for one conversation: NO_RESPONSE events, contact-limit events (a limit fired and muted the conversation permanently) and send failures (kind send_failed: the agent DID reply, the channel rejected it, the lead never saw the text that is still in the transcript; detail is `<error_code>: <description>`, e.g. THREAD_OWNER_MISMATCH = another Meta app such as ManyChat owns the Instagram thread, MESSAGE_WINDOW_EXPIRED = outside the 24h window, INVALID_TOKEN = reconnect the account). READ THE DETAIL, not just the kind: `NO_RESPONSE` alone means the agent chose silence (prompt-side); `NO_RESPONSE: last_message_not_user` means there was nothing to reply to and is benign; `NO_RESPONSE - cot_filter_blocked` means the chain-of-thought filter suppressed a leaking message (a platform safety net, see knowledge/reasoning-leak.md); `NO_RESPONSE - <text>` is the agent's own stated reason. Only the first is a prompt problem. Call this FIRST whenever an operator says the agent did not answer a specific lead, or that a lead stopped answering, before reading the prompt — an empty transcript looks identical whether the agent chose silence or the message never arrived, and a transcript with agent text looks identical whether it was delivered or rejected; this is the only way to tell. An empty result means none of those fired, so the cause is upstream (routing, trigger, connected account) — work knowledge/runbooks/agent-not-answering.md. Note NO_RESPONSE on a comment trigger suppresses BOTH legs, the public reply and the private DM.
get_conversation_decisions
Fetch real production conversations from influencer_conversation_rollup_view_rls + messages table. Returns conversation metadata and full message history. Modes: - recent: latest conversations with ≥3 messages - booking: booking link was shared with the lead - high-funnel: funnel stage ≥ 4 - high-score: Lead Score > 3 - bad: funnel ≥ 4 but lead score ≤ 3 (high funnel, low quality) - low-happy: happy_path_score < 60 - high-happy: happy_path_score ≥ 80 - stuck: agent sent ≥ 6 messages but funnel < 3 Every mode is scoped by has_agent, which defaults to "true" — only conversations an agent handled. Most accounts also carry non-agent conversations (worked by hand in the inbox, answered by an external relay, or imported when the channel was connected) and those are excluded by default. Pass has_agent: "any" or "false" to reach them. Unlike search_conversations this returns no excluded count, so if a mode looks emptier than expected, re-run it with has_agent: "any" before concluding anything. influencer_id is inferred from the JWT when using an influencer-scoped token. DELIVERY: every message carries status (OK | PENDING | FAILED); FAILED messages also carry send_failure {error_code, description}. A FAILED outbound was REJECTED by the channel and the lead never saw it, even though its text is in the transcript. Before concluding "the agent replied and the lead went quiet", check that the last outbound is not FAILED. THREAD_OWNER_MISMATCH means another Meta app (typically ManyChat) owns the Instagram thread; MESSAGE_WINDOW_EXPIRED means outside the 24h window; INVALID_TOKEN means the account must be reconnected. Returns { influencer_id, mode, count, conversations: [{ conversation_id, contact_id, contact_username, meta: {...}, messages: [{direction, author, sent_at, content, status, send_failure}] }] }. The contact_id can be passed to the WhatsApp template preview/send tools.
get_conversations
Return the stored Discord invite for the influencer's mapped operator channel (invite_url + metadata). Throws if no invite is stored — run bootstrap_discord_channel first. influencer_id is inferred from an influencer-scoped JWT; admin/API-key auth must pass it.
get_discord_invite
Fetch the influencer's recent Instagram posts via Meta Graph API. influencer_id from auth when available; from param when admin.
get_instagram_posts
Fetch the influencer's Instagram profile via Meta Graph API. influencer_id from auth when available; from param when admin.
get_instagram_profile
Fetch a specific platform knowledge document by slug. Use list_knowledge first to discover available slugs.
get_knowledge
Return the current authenticated context: influencer_id (the one active for this request), user_id, scope (single-influencer | multi-influencer | admin), available_influencer_ids (selectable via X-Influencer-Id when the token carries a user_id; multi-influencer + admin tokens), and influencers (map of influencer_id → Instagram handle — identify a creator by handle but pass the influencer_id to tools). 'scope' is the selection mode, NOT a DB role, and does not limit which tools you can call. Same shape as GET /api/v1/me.
get_me
Returns managed files (e.g. changelog.md) from peer influencers that share the same use_case or vertical as the requesting influencer. influencer_id from auth when available; from param when admin. At least one of use_case or vertical must be provided. Returns { peers: [...], total }.
get_peer_managed_files
Fetch one playbook, template, or worked-example SDK by an `id` from get_playbook_index. Prefer passing the `section` a search_playbook hit returned: you get only that heading's block instead of the whole doc (knowledge docs run 3-7k words). For sample SDKs, call with no `section` to get the file manifest, then pass `section` to select a file (e.g. system, examples, objections, keywords, meta). Large docs paginate: when has_more is true, call again with the returned next_cursor.
get_playbook_doc
Call this FIRST before creating, iterating, analyzing, or answering any question about a Ninjo agent or the cortex SDK. Returns the catalog of operating manual, knowledge base, prompt-architecture templates and worked-example SDKs; fetch the relevant ones with get_playbook_doc before drafting. The human-facing wiki is not catalogued: when an operator has to do something in the panel themselves, read `knowledge/self-serve-guide` and send them the page link. A Ninjo agent is a SYSTEM (system prompt + the 8 v5Config fields + triggers + automation), not just a prompt — the playbook is how you build the whole system instead of a bare prompt.
get_playbook_index
Fetch self-serve onboarding data from MongoDB for an influencer. Returns data from four collections: - influencer_bio: IG profile processed by GPT (bio, audience, content formats, engagement patterns) - instagram_post: Posts with metrics and video transcriptions - instagram_conversation: DM conversations with followers - creator_input: Self-serve onboarding form (program details, lead magnets, style, use case) Missing sources are listed in missing_sources — expected for incomplete onboarding. Returns { influencer_id, sections: [{ source, count?, data }], missing_sources: string[] }.
get_self_serve_data
Get message history for a Cortex thread, ordered chronologically. Supports cursor-based pagination via the `before` parameter (ISO timestamp). Returns { messages: [{ id, role, content, created_at }] }.
get_thread_messages
Get the negative config (temporary block) of a trigger. When enabled and now < expires_at, the trigger is suppressed even if it would otherwise match. Returns { negative_config } which is null if none is set. trigger_type: keywords | all-messages | comments | ads (outgoing-messages and instagram-story are not supported).
get_trigger_negative_config
Workflow activity for the last N days. fires = follow-up messages sent, or notifications sent to the operator. evaluations = all runs, including pending/failed. fires: 0 = never triggered (conditions not met), NOT a delivery failure. Returns { days, since, activity, legend }.
get_workflow_activity
List every messaging channel a Ninjo agent answers, from BOTH sources, in one unified view. Returns { channels, count }; each channel carries source: "direct" (a Meta account — Instagram/WhatsApp — connected directly in Ninjo) or "crm" (a CRM sync connection — GoHighLevel, Kommo, HubSpot, Airtable — that RELAYS its messages to this agent). Use this to tell whether an agent is a free Meta agent or is dedicated to a CRM channel: a source:"crm" channel means the agent is NOT connected to Instagram directly — it answers the messages that arrive from GHL/Kommo through that channel. `channel_type` is the account type (direct) or the CRM provider (crm); `connected` is the single 'is this channel live' flag (direct: the Meta token is valid; crm: the connection is enabled and not disconnected). Metadata only — no access tokens or webhook secrets are returned.
list_agent_channels
List all tools/skills assigned to a Ninjo agent, including their enabled status, settings, and prompt.
list_agent_tools
How do I improve a ChatGPT Plugin's discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are Ninjo alternatives on ChatGPT?
As of 2026-09-29, Ninjo competes with Botpress, Brainbase MCP, Camber, Cloud Environments, Cloud Threads, CodeWords, Codex Goals, Codex Tasks, Delegate User Codex, Dowaba AI Configuration, Expertise Live Chatbot, Graffiticode, Imagina RPG, Inistate, Kody, Manus, Mosaiq Labs, Noodle Seed, Outside Agent, Pickaxe, Plugin Creator, Plugin Editors, Roe, Tessryx, V7 Go (EU), YepCode, Zeiko Agents in ChatGPT AI Agent Builders & Deployment Platforms, ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.