# Apiway Instagram agent (MVP) > The Instagram Agent MVP automates DMs, comment-to-DM replies, and story-reaction replies on a connected Instagram Business account. This file describes the schema, service modules, queues, and error-handling contract. Source of truth: `docs/INSTAGRAM_AGENT_MVP.md`, `docs/AGENTS_INSTAGRAM.md`, `docs/INSTAGRAM_ERROR_HANDLING.md`, `docs/META_WEBHOOK_EVENT_TYPES.md`. ## Tables | Table | Purpose | |---|---| | `instagram_connections` | Per-user Instagram account, tokens, brand voice, delays, feature toggles | | `instagram_agent_events` | Unified event log (statistics + debugging) | | `instagram_kb_entries` | Knowledge base Q&A pairs per connection (RLS) | | `instagram_comment_dm_queue` | Comment-question → DM-reply queue | | `instagram_story_reaction_queue` | Story-reaction auto-reply queue | | `instagram_story_reaction_replies` | Idempotency for story reaction replies | ## `instagram_connections` columns (highlights) - `story_reaction_enabled boolean` — toggle for story-reaction auto-reply - `brand_voice_instructions text` — Gemini system prompt - `brand_language text` — fallback language when auto-detect fails - `story_mention_delay_minutes int` — per-connection delay before replying - `story_reaction_delay_minutes int` — per-connection delay before replying - `needs_reconnect boolean` — set when token error class indicates user must re-link ## Service modules (in `lib/instagram/`) - `agent-event-logger.ts` — `logAgentEvent()` helper. Always call this; statistics depend on it. - `kb-service.ts` — `matchKB(question)` finds best Q&A match for a connection; `seedDefaultKBEntries()` for first-time setup. - `comment-dm-service.ts` — `processDueCommentDms()` cron tick; takes due rows, sends Meta DM, marks done. - `story-reaction-reply-service.ts` — `processDueStoryReactionReplies()` cron tick; idempotent via `instagram_story_reaction_replies`. ## API routes - `GET/POST /api/agents/instagram/kb` — KB CRUD per connection - `GET /api/agents/instagram/stats` — statistics (events grouped, queue depth) - Webhook receiver: `POST /api/webhooks/instagram` — verifies signature, fans out to event types ## Webhook event types See `docs/META_WEBHOOK_EVENT_TYPES.md` for the full payload shape per event. Key types: - `messages` — incoming DM - `messaging_postbacks` — quick-reply taps - `comments` — feed comments (route to comment-DM queue if matches a question) - `story_reaction` — viewer reacted with an emoji - `story_replies` — viewer replied to a story - `mentions` — account was @-mentioned The webhook handler must differentiate these by **payload shape**, not just event name; Meta sends overlapping schemas. ## Error handling and `needs_reconnect` Per `docs/INSTAGRAM_ERROR_HANDLING.md`: - Catch ALL Meta API errors, classify by error code. - Token-class errors (190, 102, 463) → set `needs_reconnect=true` on the connection, surface a banner in `/app`. - Rate-limit errors (4, 17, 32) → exponential backoff in the queue worker. - Permission errors (10, 200) → block the queue, log to `instagram_agent_events` with severity `error`. NEVER let a Meta error escape unhandled into the request handler — it 500s the webhook and Meta retries indefinitely with the same bad payload. ## Brand voice (Gemini) `brand_voice_instructions` is fed to Gemini as the system prompt for every generated reply. Default fallback exists; users can override per connection. See `docs/INSTAGRAM_AGENT_MVP.md` for prompt structure and example outputs. ## SQL migration scripts (in `scripts/`) - `instagram-agent-events.sql` - `instagram-kb-entries.sql` - `instagram-comment-dm-queue.sql` - `instagram-story-reaction.sql` - `instagram-brand-voice.sql` - `instagram-delay-columns.sql` Apply via `npm run db:migrate` (uses `scripts/db-migrations.manifest.txt`). One-off: `npm run db:run -- scripts/.sql`. ## Common bugs - Forgetting to call `logAgentEvent()` → silent feature; stats page goes blank for that connection. - Comparing event types by name only → mis-routed payloads from overlapping schemas. - Not setting `needs_reconnect` on token errors → the queue keeps retrying with a stale token forever. - Skipping the idempotency check on story-reaction replies → user gets the same auto-reply 5 times. ## Cross-references - Architecture: `docs/AGENTS_INSTAGRAM.md` - Error matrix: `docs/INSTAGRAM_ERROR_HANDLING.md` - Meta webhook payloads: `docs/META_WEBHOOK_EVENT_TYPES.md` - MVP overview: `docs/INSTAGRAM_AGENT_MVP.md` - Long-form site brief: https://localhost:10000/llms-full.txt - Compact site brief (TOC): https://localhost:10000/llms.txt --- *Generated on 2026-05-01. Source: `docs/INSTAGRAM_AGENT_MVP.md`, `docs/AGENTS_INSTAGRAM.md`, `docs/INSTAGRAM_ERROR_HANDLING.md`, `docs/META_WEBHOOK_EVENT_TYPES.md`, `lib/instagram/`.*