agentOperatingProcedures-deprecation-gap.md10.0 KBView on GitHub # Deprecating `/agentOperatingProcedures` — Functionality Gap Analysis
This document answers one question before we remove the `/agentOperatingProcedures`
route: **does the "new config" actually replace it, or would we be deleting real,
load-bearing functionality with no equivalent?**
Short answer: **the new config does not replace it.** The new surfaces cover a
small subset (CRM-Updater field config) and are otherwise either a non-persistent
mockup or a persisted-but-inert authoring surface. Removing the route as-is strands
the large majority of the AOP/agent configuration UI with no replacement.
---
## 1. What "the new config" actually is
There are three candidate "new config" surfaces. Their real status:
| Surface | Route / location | Persists? | Drives execution? | Status |
| --- | --- | --- | --- | --- |
| **Agents wizard** (Routing → Agents → Skills) | `/agents` (`app/(routes)/agents/page.tsx` + `mock-data.ts`) | **No** — in-memory `let _aops` mock | **No** | 100% UI mockup; state lost on reload |
| **Playbook chip editor** (`#trigger` / `@` chips) | `/agents/playbook` (`modules/documents/playbook/`) | **Yes** (real Y.js doc at `user/playbooks/{aop}`) | **No** | Persisted but inert — see §4 |
| **CRM tab** (`CrmAgentConfigPanel` → `AgentsEditor`) | inside `/brain` (`CompanyExplorer.tsx` → `PlaybookDocTabs`) | **Yes** | **Yes** | The only genuinely wired new surface; reuses the same `aop`/`aopAgents` tRPC as the old page |
Key point: the CRM tab is **not** new functionality — it embeds the exact same
`AgentsEditor` and field editors the old page already uses, just in a different
location. The genuinely *new* surfaces (`/agents` wizard, chip-based playbook) are
not wired to execution.
The chip-editor playbook and the **execution playbook** are also two different
things: execution is driven by a separate markdown doc at
`user/playbooks/{aopId}/PLAYBOOK.md` (parsed into a `playbook_manifest`, wired into
real cron/event/field-change/before-meeting runs). The new `#trigger` chip editor
writes a sibling doc at `user/playbooks/{aop}` and **never parses a manifest on
save**, so its triggers do not execute (path mismatch + no manifest parse on the
Y.js save path).
> Note: `apps/mail/docs/playbook-implementation-state.md` predates the
> `apps/server/src/services/playbook/` execution stack and is stale on "what's wired."
---
## 2. What the old page is (why this matters)
`/agentOperatingProcedures` is a master-detail editor and the **only** UI for the
full AOP + agent configuration model. It is backed by real DB tables
(`agent_operating_procedures`, `aop_agents`, `org_aops`) and real tRPC
(`aop.*`, `aopAgents.*`), and the settings it writes actually gate and drive agent
execution, routing, and CRM behavior.
It also **exports shared components** consumed by ~16 other files — see §5.
---
## 3. Functionality that would be LOST (no equivalent in the new config)
Everything below is real (persisted + behavior-affecting) and has **no replacement**
in the `/agents` wizard or chip-based playbook. Items marked ✅ *are* reachable via
the CRM tab in `/brain` (so technically not lost, just relocated).
### AOP lifecycle & routing
1. **Create / rename / delete AOPs (conversation types)** — `aop.createAop` /
`updateAop` / `deleteAop`. Delete includes **reassigning existing conversations**
to another AOP. No new surface can create or delete an AOP.
2. **Selection criteria (routing instructions)** — `selection_procedure` column; the
text the classifier uses to route inbound messages to an AOP. No replacement.
3. **Active / Disabled (No-Op) toggle** — `isNoOp`; **gates whether agents run at
all** for the AOP. No replacement.
4. **Multi-Conversation Mode (scope config)** — `aop.updateScopeConfig` →
`conversation_scope_config`; controls `findOrCreateConversation` (multiple
conversations per company). No replacement.
5. **AOP icon & color** — `icon` / `color`; cosmetic but persisted, drives the type
badge shown across CRM/inbox. No replacement.
6. **Backfill AOP email labels** — `aop.backfillAopEmailLabels` (mutates Gmail
labels). No replacement.
### Agents
7. **Create / delete custom agents** — `aopAgents.upsert` / `delete`. ✅ (CRM tab via `AgentsEditor`)
8. **Agent enabled toggle** — `aop_agents.enabled`; disabled agents don't run. ✅
9. **Background-agent toggle** — `aop_agents.isBackground`. ✅
10. **Agent instructions (markdown doc)** — injected into the agent prompt at run time. ✅
11. **Trigger configuration** — event / cron / before-meeting / field-change, plus
natural-language condition; read by the scheduler/queue to decide when to run. ✅
12. **Output Fields picker** — `outputFieldIds`; the fields the agent populates each
run. ✅
13. **Opportunity Creation config** (CRM Updater) — inline vs. task creation of CRM
opportunities. ✅
14. **State Overview (score / notification) config** — `state_overview_config`
(deprecated in favor of `outputFieldIds`, but still settable). ✅
15. **Agent avatar** — cosmetic, persisted. ✅
16. **Agent templates** — hardcoded starter templates that instantiate real agents on
save. (The `/agents` wizard has its own *mock* templates that persist nothing.)
### Fields & display (all ✅ via the CRM tab)
17. **Status / Priority / Responsiveness enum editors** — options, colors, icons,
ordering → `conversation_field_definitions`.
18. **Custom field CRUD** — 11 types; **changing a field type migrates stored values
across all conversations** (`applyTypeConversionsToConversations`).
19. **Per-field agent permission mode** — edit / require-approval / human-only;
enforced at write time (forbidden = blocked, approval = spawns a `field-approval`
task).
20. **Per-option approval requirement** — specific enum values require approval.
21. **Per-field extra agent instructions** — appended to the field description the
agent sees.
22. **Completeness / strength scoring config** — agent writes 1–100 score + reasoning.
23. **CRM field mapping** (HubSpot / Salesforce / Attio / Copper) — transforms,
picklist seeding, write-back; saved on the connection via
`integrations.crm.updateWriteSettings`.
24. **CRM card layout** — `display_config.crmCard` (which chips, status vs. timeline).
25. **Overview-tab block layout** — `display_config.overviewTab` (blocks + `doc`
block `docPath`).
### Net gap
- **Items 1–6 and 16** (AOP lifecycle, routing, no-op gating, scope, labels,
real agent templates): **no replacement anywhere** — these are genuinely lost if
the route is removed and nothing else is built.
- **Items 7–15, 17–25**: reachable via the **CRM tab in `/brain`** (same components),
*if and only if* that tab is exposed for the AOP the user wants to edit. Today it is
surfaced per-playbook-doc inside `CompanyExplorer`, not as a general AOP editor.
---
## 4. Why the new playbook surfaces don't count as replacements (yet)
- **`/agents` wizard**: all state is module-level mock data in `mock-data.ts`. No
tRPC, no DB, lost on reload. Pure prototype.
- **`/agents/playbook` chip editor**: the doc persists, but `#trigger` blocks don't
execute. Two concrete gaps: (a) the chip editor writes `user/playbooks/{aop}` while
the executor reads `user/playbooks/{aop}/PLAYBOOK.md`; (b) the manifest is only
parsed on the agent/tool `writeDocument` path, never on the Y.js editor-save path —
so user edits never produce a `playbook_manifest`. Integration chips
(`#slack` / `#imessage` / `#mcp`) and system tokens (`@crm-updater` / `@next-steps`)
render but are inert.
---
## 5. Removal blocker: shared exports
`app/(routes)/agentOperatingProcedures/page.tsx` exports components imported by ~16
files across the app:
- `AopIconDisplay`, `IconPickerPopover`, `AOP_ICON_NAMES`, `AopIconName`, `ROUTING_ID`
Consumers include CRM cells, thread items, split-inbox tabs, folder navigation,
conversation search, onboarding, and `CrmAgentConfigPanel` itself. The sub-component
editors (`ConversationOverviewCardEditor`, `CustomFieldsEditor`,
`IntelligenceFieldsEditor`, `OverviewConfigEditor`) are likewise imported by
`/admin`, `/cedarAdmin`, `/playground`, onboarding, and the CRM tab.
**Therefore the directory cannot simply be deleted.** Removing the *route* (unrouting)
is safe and reversible; deleting the *files* requires first extracting these shared
exports into a neutral module (e.g. `modules/aop/`) and repointing all importers — a
larger refactor.
---
## 6. What "remove the route" can mean — two options
**Option A — Unroute only (safe, reversible):**
- Remove the route + layout from `apps/mail/app/routes.ts` (lines 77–79).
- Remove the nav button from `LeftSidebarContent.tsx` (the `agent` entry, lines
158–163).
- Remove `'agentOperatingProcedures'` from the `NavigationPage` union (`uxSlice.ts`)
and `navigation-page-url-sync.tsx`.
- Leave `page.tsx` + components in place (shared exports) and leave the
`aop`/`aopAgents` tRPC + DB tables + execution untouched.
- Result: page is unreachable from the UI; all underlying functionality and existing
configured AOPs keep working. Nothing is destroyed.
**Option B — Full deletion:** Option A **plus** extract the shared exports to a
neutral module, repoint ~16 importers, and delete the directory. Larger, riskier,
and still leaves AOP lifecycle/routing/no-op/scope config with **no UI at all**.
---
## 7. Recommendation
Do **not** do a full deletion yet. The new config replaces only the CRM-field/agent
subset (and only via the `/brain` CRM tab), while AOP creation, routing/selection
criteria, no-op gating, and multi-conversation scope have **no replacement**.
Recommended sequencing:
1. Decide where AOP **lifecycle + routing + no-op + scope** configuration will live
post-removal (the CRM tab does not cover these).
2. If the goal is purely to hide the page, do **Option A** (unroute + nav removal) so
nothing breaks and it's trivially reversible.
3. Defer **Option B** (file deletion / shared-export extraction) until the gap items
in §3 (1–6, 16) have a home, and the chip-playbook trigger execution (§4) is
actually wired.