Skip to main content

Bot Commands

This page is the canonical guide for commands Gigi can run today.

Documentation Rule

Every new or changed Discord command must update this page in the same change. Each command entry must include:
  • current status: live, planned, or not implemented
  • surface: slash command, DM, guild mention, prefix, button, or select menu
  • required Gigi capability
  • Discord bot permission requirements
  • options and inputs
  • example usage
  • expected response
  • failure cases
  • privacy or audit behavior
Do not document planned behavior as shipped behavior. If a command is planned, mark it planned and keep it out of the live command list.

Live Commands

/ping

Status: live for current-channel retained full memory messages. Surface: slash command. Required Gigi capability: none. Discord bot permissions: normal slash command access. Options: none. Example:
/ping
Expected response:
pong
Failure cases:
  • command is missing if slash command sync has not run
  • bot is offline if no response appears
Privacy and audit: no privileged action; no permission audit required.

DM ping

Status: live. Surface: direct message. Required Gigi capability: none. Discord bot permissions: bot must be able to receive/send DMs for that user. Example:
ping
Expected response:
pong
Failure cases:
  • user blocks bot DMs
  • bot is offline

Guild Mention ping

Status: live. Surface: guild message that mentions Gigi. Required Gigi capability: none. Discord bot permissions: read/send messages in the channel. Example:
@Gigi ping
Expected response:
pong
Failure cases:
  • bot cannot read/send in the channel
  • message does not mention Gigi
Ordinary guild messages without a Gigi mention are ignored.

Permission Commands

All /permissions commands are live. Surface: slash command. Required Gigi capability: capability.manage. Admin bootstrap: Discord guild owner or a member with Discord ADMINISTRATOR permission can pass through admin override. Responses: ephemeral. Audit: permission checks and permission changes are audited. Discord bot permissions:
  • role create requires Gigi’s bot role to have Manage Roles
  • role assign and role unassign require Manage Roles
  • Gigi’s bot role must be higher than any role it assigns, removes, or manages
  • channel membership or channel admin status is not enough

/permissions role create

Creates a Discord role and grants a preset capability set to that role. Syntax:
/permissions role create name:<role-name> preset:<preset>
Example:
/permissions role create name:Gigi Plugin Managers preset:plugin-manager
Expected response:
Created role @Gigi Plugin Managers and granted preset `plugin-manager`.
Failure cases:
  • requester lacks capability.manage and has no admin override
  • Gigi lacks Manage Roles
  • role name is missing or too long
  • preset is unknown

/permissions role assign

Assigns a Discord role to a user. Syntax:
/permissions role assign role:<role> user:<user>
Example:
/permissions role assign role:@Gigi Plugin Managers user:@person
Expected response:
Assigned role @Gigi Plugin Managers to user @person.
Failure cases:
  • requester lacks capability.manage and has no admin override
  • Gigi lacks Manage Roles
  • Gigi’s bot role is not higher than target role
  • role or user is missing

/permissions role unassign

Removes a Discord role from a user. Syntax:
/permissions role unassign role:<role> user:<user>
Expected response:
Unassigned role @Gigi Plugin Managers from user @person.
Failure cases match /permissions role assign.

/permissions role grant

Grants one capability to an existing Discord role. Syntax:
/permissions role grant role:<role> capability:<capability>
Example:
/permissions role grant role:@Gigi Plugin Managers capability:plugin.install
Expected response:
Granted `plugin.install` for role @Gigi Plugin Managers.
Failure cases:
  • requester lacks capability.manage and has no admin override
  • capability is unknown or invalid
  • role is missing

/permissions role revoke

Revokes one capability from an existing Discord role. Syntax:
/permissions role revoke role:<role> capability:<capability>
Expected response:
Revoked `plugin.install` for role @Gigi Plugin Managers.
Failure cases match /permissions role grant.

/permissions role grant-preset

Grants a preset capability set to an existing Discord role. Syntax:
/permissions role grant-preset role:<role> preset:<preset>
Example:
/permissions role grant-preset role:@Gigi Relay preset:relay-user
Expected response:
Granted preset `relay-user` for role @Gigi Relay.
Failure cases:
  • requester lacks capability.manage and has no admin override
  • preset is unknown
  • role is missing

/permissions role revoke-preset

Revokes a preset capability set from an existing Discord role. Syntax:
/permissions role revoke-preset role:<role> preset:<preset>
Expected response:
Revoked preset `relay-user` for role @Gigi Relay.
Failure cases match /permissions role grant-preset.

/permissions user grant

Grants one direct user capability exception. Syntax:
/permissions user grant user:<user> capability:<capability>
Example:
/permissions user grant user:@person capability:job.admin
Expected response:
Granted `job.admin` for user @person.
Use direct user grants only for rare audited exceptions. Prefer Discord role grants for normal access control.

/permissions user revoke

Revokes one direct user capability exception. Syntax:
/permissions user revoke user:<user> capability:<capability>
Expected response:
Revoked `job.admin` for user @person.

Presets

PresetCapabilities
gigi-admincapability.manage, plugin.install, job.admin, job.read, job.schedule, job.write, web.search, web.fetch, agent.analytics, agent.reply_latency.manage, llm.provider.write, llm.provider.test, llm.provider.select, memory.read.guild, memory.manage.guild
plugin-managerplugin.install
job-operatorjob.read, job.schedule, job.write
web-readerweb.search, web.fetch
llm-managerllm.provider.write, llm.provider.test, llm.provider.select
memory-readermemory.read.guild
memory-managermemory.read.guild, memory.manage.guild
relay-userrelay.dispatch, relay.receive

Capabilities

CapabilityWhat it allows
capability.manageGrant or revoke role/user capabilities
plugin.installInstall or configure guild external app integrations
job.adminInspect, retry, or cancel durable jobs
job.readList durable jobs through approved agent tooling
job.scheduleSchedule allowed durable jobs through confirmation-gated agent tooling
job.writeCancel queued or failed durable jobs through confirmation-gated agent tooling
web.searchRun capped public web searches through approved agent tooling
web.fetchFetch capped public text or HTML content through SSRF-filtered agent tooling
agent.analyticsView aggregate guild agent-runtime stats
agent.reply_latency.manageEnable or disable the guild reply latency footer
memory.read.guildRead permitted guild memory scope
memory.manage.guildEnable guild memory channels, configure retention, queue sync, and purge memory
relay.dispatchAsk Gigi to send a mediated message
relay.receiveReceive mediated messages from Gigi
llm.provider.writeSet, rotate, or delete guild-scoped provider credentials
llm.provider.testTest a guild-scoped provider credential without viewing it
llm.provider.selectChoose active guild provider/model and view guild usage
Dynamic external app capabilities such as plugin.run.<id> are future work and should appear only after restricted plugin authorization exists.

LLM Commands

The guild-scoped provider, model, and usage commands below are live. Personal BYOK and policy commands remain planned. Surface: slash command. Responses: ephemeral. Credential entry uses a private modal flow, not a normal slash command string option. Gigi never echoes raw provider keys. Audits for provider mutation, provider tests, and model selection include safe metadata only.

/llm provider list

Status: live. Required Gigi capability: llm.provider.write. Syntax:
/llm provider list
Expected response:
LLM provider credentials:
- `main` - `openai` (active, test: succeeded)
Failure cases:
  • requester lacks llm.provider.write
  • provider store is unavailable
Privacy and audit: lists metadata only; does not show secrets, ciphertext, nonce, or fingerprints.

/llm provider add

Status: live when GIGI_LLM_SECRET_KEY_BASE64 is configured. Required Gigi capability: llm.provider.write. Syntax:
/llm provider add provider:<openai|anthropic|gemini|custom> label:<label>
Expected response: private modal titled Add LLM Credential. Failure cases:
  • requester lacks llm.provider.write
  • credential entry is not configured
  • provider is unknown
  • label is missing, too long, or looks sensitive
Privacy and audit: submitted credential value is sealed before storage. Audit metadata records action and provider only.

/llm provider test

Status: live. Required Gigi capability: llm.provider.test. Syntax:
/llm provider test label:<label>
Expected response:
Tested `openai` credential `main`: succeeded.
Failure cases:
  • requester lacks llm.provider.test
  • credential label is missing or unknown
  • provider probe fails
Privacy and audit: response and audit omit raw secrets and provider responses. Last test status is stored on credential metadata.

/llm provider rotate

Status: live when GIGI_LLM_SECRET_KEY_BASE64 is configured. Required Gigi capability: llm.provider.write. Syntax:
/llm provider rotate label:<label>
Expected response: private modal titled Rotate LLM Credential. Failure cases:
  • requester lacks llm.provider.write
  • credential entry is not configured
  • active credential label is unknown
Privacy and audit: same private modal and safe audit rules as /llm provider add.

/llm provider delete

Status: live. Required Gigi capability: llm.provider.write. Syntax:
/llm provider delete label:<label> confirm:true
Expected response:
Revoked LLM credential `main`.
Failure cases:
  • requester lacks llm.provider.write
  • confirm is not true
  • credential label is unknown
Privacy and audit: audits safe deletion metadata only.

/llm model show

Status: live. Required Gigi capability: llm.provider.select. Syntax:
/llm model show purpose:<chat|reasoning|embedding|routing>
Expected response:
Active `chat` model: `gpt-4o-mini` via `openai` (`credential-id`).
Failure cases:
  • requester lacks llm.provider.select
  • purpose is unknown
  • no active profile exists for that purpose
Privacy and audit: metadata only; no raw secret access is shown.

/llm model set

Status: live. Required Gigi capability: llm.provider.select. Syntax:
/llm model set purpose:<chat|reasoning|embedding|routing> label:<label> model:<auto|model-id>
Expected response:
Selected `gemini-3.5-flash` for `chat` using credential `main` (auto default for Gemini).
model is optional. If omitted or set to auto, Gigi selects a static default based on the credential provider and purpose. Pass a provider model ID to override the default. Failure cases:
  • requester lacks llm.provider.select
  • purpose, label, or model is invalid
  • no default exists for that provider and purpose
  • selected provider does not support that purpose
Privacy and audit: audits provider, purpose, and model metadata only.

/llm routing show

Status: live. Required Gigi capability: llm.provider.select. Syntax:
/llm routing show
Expected response:
LLM tool routing mode: `off`.

/llm routing set

Status: live. Required Gigi capability: llm.provider.write. Syntax:
/llm routing set mode:<off|dry-run|enabled>
Modes:
  • off: deterministic mention routing only; no LLM tool planner calls.
  • dry-run: LLM may propose memory or external-app tool calls, but Gigi does not execute read-only memory tools or semantic public dispatch.
  • enabled: LLM may route to allowed native memory tools and public external app dispatch after validation and capability checks.
Privacy and audit: audits routing mode metadata only.

/llm usage guild

Status: live. Required Gigi capability: llm.provider.select. Syntax:
/llm usage guild
Expected response:
LLM usage for this server: 46 tokens (12 input, 34 output) across 3 requests; 1 failed.
Failure cases:
  • requester lacks llm.provider.select
  • usage store is unavailable
Privacy and audit: reads aggregate token and request counts only. Usage events do not store raw prompts, completions, provider responses, or secrets. This command remains the aggregate token/provider usage view. It is separate from the optional reply latency footer controlled by /agent stats guild reply-latency:on|off.

Agent Commands

Guild mention boundary

Guild mentions are conversational agent input, not a broad heuristic command parser. Current deterministic pre-planner behavior should stay narrow: liveness ping, enabled external app prefix matching, and exact current-channel memory count questions documented below. Flexible mention text should route through LLM planning, registered tools, policy checks, and answer composition. For explicit behavior, prefer exact slash commands such as /ask, /memory count, /plugins dry-run, /llm routing show, and /agent trace last. Slash commands are the deterministic source for stable syntax, required capabilities, response shape, and failure cases.

/ask

Status: live. Required Gigi capability: none for context:none; dynamic channel context and channel memory tools require memory.read.guild when context:channel and tool routing are enabled. Syntax:
/ask question:<text> context:<none|channel> visibility:<public|private>
context:none routes through agent chat without memory fetches. context:channel lets the agent load permitted retained messages from this channel into a bounded context pack and allows the planner to choose current-channel memory tools such as memory.count, memory.search, and memory.recent when /llm routing allows it and the requester has memory.read.guild. For guild mentions, if the planner determines no tool or fetched/prior agent context is needed, the agent path yields to the normal chat handler instead of composing an empty tool-result answer. Evidence labels such as [S1] are validation markers for agent answer composition and are removed before Discord delivery. If visibility is omitted, context:none defaults to public and context:channel defaults to private. A private agent response also forces an ephemeral slash response even if the request asked for public visibility. Examples:
/ask question:explain recursion in one paragraph context:none visibility:private
/ask question:how often did we mention postgres here context:channel
Privacy and audit: dynamic context fetches are scoped to the current guild channel and require enabled memory plus memory.read.guild. The agent path records scoped metadata such as run IDs, step indexes, context scope, source type, result count, truncation flag, tool names, status, capabilities, source IDs, message IDs, citation labels, restore handles, context-pack status markers, run status, and termination reason. It does not store raw prompt text, raw memory snippets, provider responses, embeddings, planned commands, or secrets in audit metadata or durable step observations. Follow-up snapshots omit memory evidence summaries and provenance from memory.search and memory.recent tool data. Failure cases and notes:
  • context:channel but channel memory is off may leave Gigi with no fetched snippets
  • requester lacks memory.read.guild
  • /llm routing is off or tool routing is unavailable
  • context packs may be truncated because of budget; Gigi should still answer from the bounded pack
When a durable run needs confirmation, Gigi includes the run ID in the response and points to /agent pending, /agent confirm, and /agent reject. Confirming or rejecting updates the pending confirmation record; confirmed actions are not resumed automatically in this slice.

/agent trace last

Status: live. Required Gigi capability: none. The command only shows your own last agent run in the current channel. Syntax:
/agent trace last visibility:<private|public?>
Expected response:
Last agent run `agentrun_...`:
status: `succeeded`
- `plan` succeeded routing=`enabled`
- `1` `tool` succeeded tool=`memory.recent` kind=`read`
- `2` `answer` succeeded
Use this after a guild mention or /ask request to see which planner/tool/answer path Gigi used. The default response is private. Failure cases:
  • no prior agent run exists for you in this channel
  • trace storage is unavailable in the current process
Privacy and audit: trace output is safe metadata only. It does not include raw prompts, raw memory snippets, provider responses, secrets, or raw external commands.

/agent stats guild

Status: live. Surface: slash command. Required Gigi capability: agent.analytics for aggregate stats. reply-latency:on|off requires agent.reply_latency.manage. Discord bot permissions: normal slash command access. Options:
  • period: optional fixed window, one of 24h, 7d, 30d, or all; defaults to 7d.
  • reply-latency: optional guild setting toggle, either on or off; enables or disables the reply latency footer for future guild replies.
Syntax:
/agent stats guild
/agent stats guild period:7d
/agent stats guild reply-latency:on
/agent stats guild reply-latency:off
Example:
/agent stats guild period:7d
/agent stats guild reply-latency:on
Expected response:
Agent stats for this server (last 7 days):
runs: `9` total (`6` succeeded, `2` failed, `1` canceled)
latency: avg `1.5s`, p50 `1.0s`, p95 `3.0s`, max `4.0s`
steps: `21` total, `14` tool, `5` llm
top reasons: `planner_failed` `2`; `tool_failed` `1`
top tools: `memory.search` `3` ok / `1` failed; `permissions.check` `2` ok / `0` failed
When reply-latency is provided, Gigi updates the guild setting and reports the new state. reply-latency:on enables a footer on future guild replies; reply-latency:off disables it. Use this to inspect aggregate agent-runtime health for the current server. The stats response is ephemeral. If no period is provided, Gigi uses 7d. If no runs match the selected period, Gigi returns a zero-run aggregate summary for that window. The reply latency footer is not token usage, provider usage, or billing data; it is response elapsed wall time. Failure cases:
  • requester lacks agent.analytics for aggregate stats, or agent.reply_latency.manage for the reply latency setting
  • command is used outside a guild
  • stats permission is not configured
  • stats storage is unavailable
Privacy and audit: reads aggregate guild counters only. It may show aggregate latency, status counts, termination reasons, and top tool names, but it does not show user IDs, per-user prompts, raw prompt text, memory snippets, provider responses, tool arguments, planned commands, secrets, or individual run details. Reply latency footer privacy: when enabled, the footer exposes only response elapsed time. It does not expose token counts, provider usage, raw prompts, snippets, tool arguments, provider responses, or per-user details.

/agent cancel

Status: live. Required Gigi capability: none for the run owner; Discord administrators can cancel another user’s run in the same server. Syntax:
/agent cancel run:<agent-run-id>
Expected response:
Cancellation requested for agent run `agentrun_...`.

/agent pending

Status: live. Required Gigi capability: none for the run owner; Discord administrators can inspect another user’s pending confirmation in the same server. Syntax:
/agent pending run:<agent-run-id>
Expected response:
Pending confirmation for agent run `agentrun_...`.
Tool: `plugin.dispatch`.
Step: `1`.
Confirmation: `agentconfirm_...`.

/agent confirm

Status: live. Required Gigi capability: none for the run owner; Discord administrators can resolve another user’s pending confirmation in the same server. Syntax:
/agent confirm run:<agent-run-id>
Expected response:
Confirmed pending agent action `plugin.dispatch` for run `agentrun_...`.

/agent reject

Status: live. Required Gigi capability: none for the run owner; Discord administrators can resolve another user’s pending confirmation in the same server. Syntax:
/agent reject run:<agent-run-id>
Expected response:
Rejected pending agent action `plugin.dispatch` for run `agentrun_...`.
Agent command privacy and audit: run management and stats responses are ephemeral. Run-management audit metadata may include action names, run IDs, confirmation IDs, tool names, and step indexes; stats audit metadata records the stats scope, period, and required capability. Audit events do not include raw prompts or raw tool arguments.

Planned LLM Commands

These commands are not implemented yet.

/llm policy set

Status: planned. Required Gigi capability: llm.provider.write. Planned syntax:
/llm policy set personal-keys:<off|dm-only|guild-allowed>
V1 personal BYOK command direction:
/llm key add provider:<openai|anthropic|gemini|custom> label:<label>
/llm key test label:<label>
/llm key prefer surface:<dm|guild> label:<label>
/llm key remove label:<label>
Credential entry should use a private modal or private flow, not a normal slash command string option. Gigi should never echo, log, or audit raw provider keys. Personal BYOK pays for reasoning but does not grant Gigi action capabilities.

Memory Commands

Guild memory starts off, requires explicit per-channel opt-in, and runs live ingestion through a bounded async queue so Discord message handling stays responsive.

Guild mention memory questions

Status: live for exact current-channel count questions matching how many times did @user mention "text"? and, when LLM tool routing is enabled, flexible current-channel count/search phrasing. Required Gigi capability: memory.read.guild. Example:
@Gigi how many times did @sam mention "postgres"?
@Gigi how many times has postgres been mentioned in this channel?
Example response:
@sam mentioned `postgres` 14 times in this channel.
Messages mentioned `postgres` 19 times in this channel.
Count answers use deterministic SQL over indexed messages. When LLM tool routing is enabled, Gigi may use the routing model to choose the memory tool, but it does not ask an LLM to guess aggregate counts. Failure cases:
  • requester lacks memory.read.guild
  • memory is not enabled for the guild or channel
  • target user or text is ambiguous
  • indexed data is not ready yet
  • requester cannot view channels that contain matching messages

/memory count

Status: live for this-channel exact counts over retained full memory messages. Required Gigi capability: memory.read.guild. Syntax:
/memory count text:<string> user:<user?> scope:<this-channel|server>
Use this for exact normalized aggregate questions. The response is ephemeral. server scope is reserved until channel-visibility filtering lands. Status: live. Required Gigi capability: memory.read.guild. Syntax:
/memory search query:<string> user:<user?> limit:<number?>
Returns matching normalized evidence for the current channel with safe author metadata, message IDs, citation labels, source IDs, restore handles, retrieval time, and retention proof. Cross-channel search waits for channel-visibility filtering.

/memory ask

Status: planned. Required Gigi capability: memory.read.guild. Syntax:
/memory ask question:<string> scope:<this-channel|server> since:<date?> include-sources:<true|false>
Uses retrieval plus a configured guild chat model to answer with citations. Semantic retrieval also needs a guild embedding model profile.

/memory status

Status: planned. Required Gigi capability: memory.read.guild. Syntax:
/memory status
Shows configured channel modes, retention, default storage mode, and embedding policy. Response is ephemeral.

/memory sync

Status: live for show and channel set. Required Gigi capability: memory.manage.guild. Syntax:
/memory sync channel:<channel?> since:<date?> confirm:true
Queues a resumable backfill job and returns immediately. Workers should fetch Discord history page by page, checkpoint progress, batch inserts, and batch embeddings without blocking the bot.

/memory settings

Status: planned. Required Gigi capability: memory.manage.guild. Syntax:
/memory settings show
/memory settings set channel:<channel> mode:<off|metadata|full> retention-days:<number?>
metadata mode stores message hashes only in this slice. full mode stores normalized text for current-channel counts and future search/retrieval. Retention is required before ingest.

External App Mention Actions

External app matching is live for guild mentions. Deterministic prefix matching runs first against manifest actions. If no prefix trigger matches and /llm routing is dry-run or enabled, semantic routing can call the configured routing model, validate the proposal against enabled manifests, and apply capability checks. dry-run returns the planned action only. enabled may dispatch public send_message actions only when the approved version has stored public-dispatch consent; restricted actions still dry-run. It does not call LangChain, run harnesses, or use LLM output as dispatch authority. Dispatch is opt-in per approved version and per action. If a matched action has dispatch: "send_message", safety: "public", empty permissions, and stored public-dispatch consent from import, Gigi sends the planned prefix command into the channel as Gigi. If the action omits that dispatch mode, lacks stored consent, or has non-empty permissions, Gigi returns a dry-run response instead. Prefix trigger value is the command Gigi sends. Trigger aliases are optional user-facing phrases Gigi can match from the mention. For example, a manifest can match @Gigi play never gonna give you up and dispatch m!play never gonna give you up. External apps may ignore bot-authored messages. Gigi can send !play ...; the external app decides whether to act. Surface: guild mention message. Required Gigi capability: the matched action’s permissions entry. If an action has no permissions, it is public for guild members after the plugin is enabled. Audit: matched, denied, failed dry-run, and sent dispatch attempts are audited without storing raw message text or the planned command. Syntax:
@Gigi play never gonna give you up
@Gigi !play never gonna give you up
Expected response:
Matched external app: `Jockie Music`.
Planned command: `!play never gonna give you up`.
Dry-run only; no command sent.
Expected response when the enabled action opts into public send_message dispatch:
!play never gonna give you up
Failure cases:
  • no enabled external app manifest matches the text and semantic routing cannot produce a valid dry-run plan, so Gigi falls back to normal mention behavior
  • requester lacks the matched action permission and has no Discord administrator override; public actions with empty permissions do not require this check
  • database is unavailable
  • action trigger or surface does not match the message
  • routing model profile or sealed guild credential is missing for semantic routing
  • external app ignores bot-authored messages after Gigi sends the command
If mention routing is silent, use /plugins dry-run to test the same enabled manifest matcher through slash commands. This avoids Discord message-content delivery issues and proves whether import, enable, and trigger matching work.

Plugin Commands

All /plugins commands are live admin commands for the external app manifest catalog. They never dispatch external app commands; only guild mention routing can send an opted-in public command. Surface: slash command. Required Gigi capability: plugin.install. Admin bootstrap: Discord guild owner or a member with Discord ADMINISTRATOR permission can pass through admin override. Responses: ephemeral. Audit: import, enable, and disable changes are audited. Discord bot permissions: normal slash command access.

/plugins list

Lists approved external app manifests in the catalog. Syntax:
/plugins list
Expected response:
Approved plugins:
- `example-tool@1.0.0` - Example Tool
Failure cases:
  • requester lacks plugin.install and has no admin override
  • database is unavailable

/plugins import-manifest

Fetches gigi-plugin.json from HTTPS, validates it, and stores it as an approved external app manifest. Syntax:
/plugins import-manifest url:<https-url> allow-public-dispatch:<true|false?>
Expected response:
Imported plugin `Example Tool` (`example-tool@1.0.0`).
Failure cases:
  • requester lacks plugin.install and has no admin override
  • URL is missing, is not HTTPS, or includes user info, query, or fragment data
  • manifest is too large
  • manifest JSON is invalid
  • manifest lacks exact Discord application ID or bot user ID
  • manifest fails capability, trigger, surface, audit, or attribution validation
If any action declares dispatch: "send_message" with safety: "public" and empty permissions, allow-public-dispatch:true is required and stored on the approved version. URL imports reject unsafe literal hosts, DNS-resolved unsafe addresses, unsafe redirects, and non-JSON manifest responses. Privacy and audit: raw URLs are not written to audit metadata. Manifests must not contain secrets, private Discord content, private URLs, signed URLs, or guessed behavior.

/plugins import-file

Imports an uploaded gigi-plugin.json attachment, validates it, and stores it as an approved external app manifest. Syntax:
/plugins import-file attachment:<json-file> allow-public-dispatch:<true|false?>
Expected response:
Imported plugin `Example Tool` (`example-tool@1.0.0`) from uploaded file.
Failure cases:
  • requester lacks plugin.install and has no admin override
  • attachment is missing or cannot be resolved by Discord
  • attachment filename does not end in .json
  • manifest is too large
  • manifest JSON is invalid
  • manifest lacks exact Discord application ID or bot user ID
  • manifest fails capability, trigger, surface, audit, or attribution validation
If any action declares dispatch: "send_message" with safety: "public" and empty permissions, allow-public-dispatch:true is required and stored on the approved version. Attachment imports reject non-JSON attachment content types when Discord provides a content type and reject unsafe redirects. Privacy and audit: Discord attachment URLs are not stored in audit metadata or manifest source metadata. Uploaded manifests are normalized to source_kind: "uploaded_file" and manifest_url is cleared.

/plugins enable

Enables an approved external app version for the current Discord server. This permits matching. Dispatch still depends on the matched action declaring dispatch: "send_message", safety: "public", empty permissions, and stored public-dispatch consent from import. Syntax:
/plugins enable plugin:<plugin-id> version:<version>
Expected response:
Enabled plugin `example-tool@1.0.0` for this server.
Failure cases:
  • requester lacks plugin.install and has no admin override
  • plugin id or version is missing
  • approved plugin version does not exist
  • database is unavailable

/plugins disable

Disables an external app integration for the current Discord server. Syntax:
/plugins disable plugin:<plugin-id>
Expected response:
Disabled plugin `example-tool` for this server.
Failure cases:
  • requester lacks plugin.install and has no admin override
  • plugin id is missing
  • enabled plugin is not found
  • database is unavailable

/plugins enabled

Lists external app integrations enabled for the current Discord server. Syntax:
/plugins enabled
Expected response:
Enabled plugins:
- `example-tool@1.0.0` - Example Tool
Failure cases:
  • requester lacks plugin.install and has no admin override
  • database is unavailable

/plugins dry-run

Tests enabled external app trigger matching without using message content events and without sending commands to the external app. This command always dry-runs, even if the matched action has dispatch: "send_message". Syntax:
/plugins dry-run text:play never gonna give you up
Expected response:
Matched external app: `Jockie Music`.
Planned command: `!play never gonna give you up`.
Dry-run only; no command sent.
Failure cases:
  • requester lacks plugin.install and has no admin override
  • no enabled manifest matches the text
  • database is unavailable

Not Implemented Yet

  • rich DM chat
  • semantic /memory ask, cross-channel retrieval, and citation-rich retrieval
  • tasks
  • relay actions
  • LLM-driven external app dispatch
  • restricted external app command dispatch
  • confirmed per-message dispatch approval