Skip to content

AGENTS.md

104 lines · 3.6 KB · Markdown
Raw

@kody/discord — agent notes

Human setup and intent live in README.md. This file is for agents: imports, smoke/dryRun snippets, and edge cases. Secrets by name only — never paste token values. Do not disable live webhooks or jobs.

Secrets / integrations

LaneCredentialDefault name
Bot tokenUser secretdiscordBotToken
User OAuthSaved integrationdiscord

Override with secretName (bot) or integration (OAuth). Extra accounts: discord-work / discordBotTokenWork — never hard-code personal aliases.

Import paths

ExportImport
overviewkody:@kody/discord
smoke-testkody:@kody/discord/smoke-test
get-mekody:@kody/discord/get-me
list-guildskody:@kody/discord/list-guilds
fetch-channelkody:@kody/discord/fetch-channel
fetch-channel-messageskody:@kody/discord/fetch-channel-messages
post-messagekody:@kody/discord/post-message
edit-messagekody:@kody/discord/edit-message
add-reactionkody:@kody/discord/add-reaction
create-threadkody:@kody/discord/create-thread
list-channel-threadskody:@kody/discord/list-channel-threads

Prefer static kody:@kody/discord/... imports from execute. Static imports run in this package's runtime so secret mounts resolve.

Smoke test (read-only)

Bot lane (reads approved discordBotToken):

import smokeTest from 'kody:@kody/discord/smoke-test'

export default async function main() {
	return await smokeTest({ lane: 'bot' })
}

OAuth lane:

import smokeTest from 'kody:@kody/discord/smoke-test'

export default async function main() {
	return await smokeTest({ lane: 'oauth', integration: 'discord' })
}

Static identity read (OAuth):

import getMe from 'kody:@kody/discord/get-me'

export default async function main() {
	return getMe({ lane: 'oauth', integration: 'discord' })
}

dryRun / confirm (mutations)

Mutations (post-message, edit-message, add-reaction, create-thread) accept dryRun: true (preview payload, no API write). Live writes require confirm: true after the user approved the exact channel and content.

import postMessage from 'kody:@kody/discord/post-message'

export default async function main() {
	return postMessage({
		channelId: '1234567890',
		content: 'Hello from Kody',
		dryRun: true,
	})
}

Edge cases

  • OAuth never grants channel content — use the bot lane for messages/reactions/threads.
  • Empty message content on an otherwise successful read: enable Message Content on the Bot tab.
  • Helpers throw DiscordApiError with missingScope and nextStep on 401/403.
  • OAuth 401/403: reconnect at /connect/oauth?provider=…&scopes=…. Do not cache raw tokens (7-day expiry).
  • Bot 401: rotate/save discordBotToken. Package always sends the Bot prefix.
  • Bot 403 code 50001 Missing Access: bot not in server / cannot see channel — reinstall with scope=bot.
  • Bot 403 code 50013 Missing Permissions: grant missing channel permission or privileged intent, then retry.
  • list-channel-threads requires both channelId and guildId.
  • Discord rate-limits reactions aggressively — add sequentially and honor retry_after on HTTP 429.
  • Only messages posted by the same bot can be edited.

Fork / adapt

  1. Fork this listing into the caller's account (kody id stays discord).
  2. Connect their bot secret and/or OAuth integration; approve discord.com.
  3. Run ./smoke-test for each lane before treating the copy as ready.
  4. Keep LICENSE, ## Intent, and community-icon.svg intact for community listing.