e9-custom-fields
Skill1 starsChanged 48 days agoApache-2.0View on GitHub
Add vendor custom fields to an installed plugin's data pull (people, transactions/gifts/donations, and other submodules) by appending to the engine9 plugin setting `<submodule>_custom_fields` (people_custom_fields, transaction_custom_fields) through MCP `plugin` settings / setSetting. Covers locating the account and plugin, the hard stop when no setting exists (legacy Frakture-only accounts, method-option-only plugins), listCustomFields, dedupe-and-append, optional varchar(255) columns on `<table_prefix>person` / `<table_prefix>transaction` tables, and an optional backdating load. Use when asked to add, pull, or sync custom fields, extra fields, or additional columns from a CRM or vendor plugin.
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 1 is distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 64
Call account plugins. Note each candidate's path, id (plugin uuid), table_prefix, and metadata.submodules.
- Very specific: line 71
Call plugin settings for the account, filtered by path or plugin_id when known.
- Very specific: line 100
Read the current value from the settings response.
- Very specific: line 116
Call settings again and confirm the stored value.
- Distinctive: line 120
Ask whether the new fields must also land in existing warehouse tables.
- Very specific: line 122
When yes, find candidates with sql tables using the plugin table_prefix (^<table_prefix>person, ^<table_prefix>transaction).
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Add custom fields to a plugin pull
A plugin's people or transaction pull brings in standard fields plus any vendor custom fields named in a plugin setting. Adding fields means appending names to that setting, never replacing it. Use this skill when someone asks to add one or more custom fields to a people, transaction, gift, or donation pull for an account. The work is MCP-only and starts with a check that the setting exists; when it does not, stop.
Quick reference
| Step | MCP call |
| Find the account | account { "command": "search", "prefix": "<account_id>" } |
| Find the plugin and submodule | account { "command": "plugins", "account_id": "<account_id>" }, plus recent runs with task { "action": "list", "search": "<plugin>", "include_task_runs": true } |
| Confirm the setting exists (gate) | plugin { "command": "settings", "account_id": "<account_id>", "path": "<plugin path>" } |
| List available custom fields | task { "path": "<plugin path>:<Submodule>", "method": "listCustomFields" } |
| Append the fields | plugin { "command": "setSetting", "plugin_id": "<uuid>", "name": "<setting>", "value": [...] } |
| Find existing tables (optional) | sql { "command": "tables", "filter": "^<table_prefix>(person|transaction)" } |
| Add columns (optional, after asking) | sql ALTER TABLE <table> ADD COLUMN <field> varchar(255) |
| Backdate (optional, after asking) | task with the submodule's load method (not timeWalk) and a bounded start / end |
| Submodule | Setting |
| People | people_custom_fields |
| Gifts, Donations, Transactions | transaction_custom_fields |
| Other submodules | <submodule>_custom_fields. Confirm the name and section in the settings catalog |
Rule: The setting name and section come from MCP plugin settings. The table above is the convention, not a substitute for checking.
Concepts
Engine9 plugin settings live in the warehouse setting table, one set per plugin row. Submodule settings carry section: "<Submodule>" in the catalog. A *_custom_fields setting is an array of vendor field identifiers that the pull requests in addition to standard fields.
Older plugins accept a custom_fields option on the load method itself, set in each dataflow job. That is the legacy mechanism. This skill does not edit method options.
Modern pulls write to input-store files, not database tables. Some accounts also keep plugin-prefixed warehouse tables (<table_prefix>person, <table_prefix>transaction) that need a matching column before new fields show up there.
Workflow
- [ ] A. Account and plugin found (MCP only)
- [ ] B. <submodule>_custom_fields setting exists — otherwise HARD STOP
- [ ] C. listCustomFields run on the right submodule
- [ ] D. Requested fields matched to exact identifiers
- [ ] E. Setting updated: existing values kept, new values deduped and appended
- [ ] F. Asked whether existing tables need varchar(255) columns
- [ ] G. Offered a backdating loadA. Find the account and plugin
- Log in and search the account per e9-mcp. A
count: 0miss is a stop. - Call
accountplugins. Note each candidate'spath,id(plugin uuid),table_prefix, andmetadata.submodules. - When several instances of the vendor plugin exist, or it is unclear which job is the pull, list recent flow runs with
taskaction: "list", asearchon the vendor name, andinclude_task_runs. The running job's plugin path and submodule (for example...RENxtBot.Peoplewith methodloadPeople) identify the pull.
Rule: Discover the plugin from MCP only. Do not read local account configs or plugin source.
B. Confirm the setting exists (hard stop gate)
Call plugin settings for the account, filtered by path or plugin_id when known. Look for a setting named <submodule>_custom_fields with section equal to the submodule.
Rule: If the setting is not in the catalog, stop. Report what was checked and end the workflow. There is no point listing fields that cannot be saved.
Each of these is a hard stop:
| Signal | Meaning |
account plugins returns [] and plugin settings returns plugins: [] | The account has no engine9 plugin rows. Typical of a legacy Frakture-only warehouse (no plugin table; plugins appear only in bot_metadata) |
engine9 is deployed (core @engine9/schemas/* rows exist) but the vendor plugin is not in account plugins, and its package is not in plugin listAvailable | The vendor integration still runs only as a Frakture bot. It cannot be installed on this server, so it has no settings |
The plugin is in settings but has no <submodule>_custom_fields | The package does not declare the setting |
task describe shows custom_fields only as an option on the load method | Legacy method-option mechanism only |
Rule: Do not work around a missing setting. Do not edit custom_fields on dataflow jobs, run addCustomField, or change the load flow unless the user explicitly asks for that legacy path.
C. List custom fields
Schedule the submodule's listCustomFields with task (path = <plugin path>:<Submodule>, method: "listCustomFields", and plugin_id when more than one instance exists). Poll with action: "listTasks" and read the result with action: "output".
Rule: Run it on the submodule that matches the setting. People custom fields and gift custom fields are separate catalogs in most CRMs.
D. Match the requested fields
Match the user's names, which are often vendor UI labels, to the identifiers returned by listCustomFields. Use the identifier form that the setting's current values use.
Rule: When a requested name matches zero or several fields, show the candidates and ask. Do not guess.
E. Append to the setting
- Read the current
valuefrom the settings response. It may be an array or a comma-separated string. - Build the new list: every existing value in its original order, then each new identifier not already present (case-insensitive compare).
- Show before and after, then call
setSettingwith the full array.
{
"command": "setSetting",
"account_id": "<account_id>",
"plugin_id": "<plugin uuid>",
"name": "people_custom_fields",
"value": ["existing_field_a", "existing_field_b", "new_field_c", "new_field_d"]
}Rule: Append only. Do not remove or reorder existing custom fields without explicit guidance from the user.
- Call
settingsagain and confirm the stored value.
F. Existing tables (ask first)
Ask whether the new fields must also land in existing warehouse tables. Modern pulls keep data in files, so the answer is often no.
When yes, find candidates with sql tables using the plugin table_prefix (^<table_prefix>person, ^<table_prefix>transaction). Ignore _archive_* tables. Check describe for columns that already exist, then add only the missing ones:
ALTER TABLE <table_prefix>person ADD COLUMN <field> varchar(255)Rule: New columns are varchar(255) unless the user specifies a type.
Rule: DDL needs the admin role. Show the exact statements and get confirmation before running them.
G. Backdate (optional)
The setting only affects future pulls. To fill history, offer to schedule the submodule's load method with a bounded window. Check its options first with task describe (start / end, interval, table). Use load with a bounded start / end / interval (for example start: "now", end: "2010-01-01", interval: "3M") rather than start: "none".
Rule: Prefer the submodule's load method over a timeWalk method. Use timeWalk only when task describe shows the submodule has no load method, and tell the user why.
{
"account_id": "<account_id>",
"path": "<plugin path>:Gifts",
"method": "load",
"plugin_id": "<plugin uuid>",
"options": { "start": "now", "end": "2020-01-01", "interval": "3M" }
}Rule: Offer the backdate; do not schedule it without confirmation. A wide pull can be large and hit vendor rate limits.
Rule: Cap the backfill end at 2010-01-01 unless the user explicitly asks to go further. Do not walk to the account's earliest transaction, 1900-01-01, or start: "none" without that explicit request. Frakture load also rejects more than 500 intervals — stay under that limit (for example, 3M from now to 2010 is fine; 3M to 1900 is not).
Rule: When splitting is required to stay under 500 intervals, still respect the 2010 cap unless the user waived it.
Troubleshooting
| Symptom | Action |
account plugins is empty but sql shows <prefix>_person tables | Legacy Frakture-only account. Hard stop at step B; report it |
engine9 was just deployed and only core @engine9/schemas/* rows exist | Vendor plugin rows (with remote_plugin_id set to the Frakture bot id) can be added after the deploy. Re-check plugin settings before reporting a hard stop |
The dataflow job already passes custom_fields as a method option | Copy those fields into the setting (append) when the user asks, then omit custom_fields on backfill jobs so the setting is the only source |
| Setting exists but the value is a string | Split on commas, trim, then append and write back an array |
Log reads the setting (select name, value from setting … name='<setting>') and then says No custom_fields, not getting custom fields | The plugin read the setting but did not apply it (for example, a JSON string value that is never parsed). The load will not populate the columns. Report it as a plugin bug; passing custom_fields as a method option on that job is the workaround, with the user's approval |
| New fields missing after the next pull | Confirm the stored setting value; check the pull's log; check whether the target table needs the column (step F) |
setSetting validation error | Match the declared type (array); send JSON, not a quoted list |
Related documentation
- MCP tools
- Plugin install and settings
- Declaring plugin settings
In this repository24 other files it gives its agents.
- .cursor/rules/no-client-names.mdcCursor rule
- .cursor/rules/skill-writing-standard.mdcCursor rule
- create-engine9-pluginSkill
- e9-api-keySkill
- e9-cliSkill
- e9-delegate-domainSkill
- e9-dev-tasksSkill
- e9-eqlSkill
- e9-exportSkill
- e9-funnelSkill
- e9-global-messageSkill
- e9-inputSkill
- e9-inventorySkill
- e9-mcpSkill
- e9-modelSkill
- e9-person-idSkill
- e9-person-remoteSkill
- e9-pii-freeSkill
- e9-pluginSkill
- e9-reportsSkill
- e9-source-codeSkill
- e9-tasks-apiSkill
- e9-timelineSkill
- e9-upgradeSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

