@agentled/cli 0.8.3 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +3 -2
  2. package/dist/commands/agents.js +1 -5
  3. package/dist/commands/agents.js.map +1 -1
  4. package/dist/commands/executions.js +15 -0
  5. package/dist/commands/executions.js.map +1 -1
  6. package/dist/commands/feedback.js +13 -2
  7. package/dist/commands/feedback.js.map +1 -1
  8. package/dist/commands/workspace.js +3 -3
  9. package/dist/commands/workspace.js.map +1 -1
  10. package/package.json +2 -2
  11. package/patterns/v1/03-credit-efficiency.md +4 -4
  12. package/skills/agentled/SKILL.md +4 -2
  13. package/skills/agentled/references/credits-apps-and-errors.md +1 -1
  14. package/skills/agentled/references/step-schemas.md +21 -0
  15. package/skills/agentled-content/SKILL.md +52 -0
  16. package/skills/agentled-content/references/context.md +21 -0
  17. package/skills/agentled-content/templates/workspace/AGENTS.md +5 -0
  18. package/skills/agentled-content/templates/workspace/brand.md +15 -0
  19. package/skills/agentled-content/templates/workspace/company.md +11 -0
  20. package/skills/agentled-content/templates/workspace/content/guidelines.md +6 -0
  21. package/skills/agentled-content/templates/workspace/first-task.md +5 -0
  22. package/skills/agentled-content/templates/workspace/onboarding.md +5 -0
  23. package/skills/agentled-content/templates/workspace/tools.md +5 -0
  24. package/skills/agentled-content/tools.md +8 -0
  25. package/skills/agentled-content-visuals/SKILL.md +35 -0
  26. package/skills/agentled-content-visuals/references/quality-checks.md +9 -0
  27. package/skills/gtm-operator/SKILL.md +443 -39
  28. package/skills/seo-operator/SKILL.md +35 -0
  29. package/skills/social-media-agent/SKILL.md +2 -2
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: agentled-content-visuals
3
+ version: 0.2.1
4
+ description: Generate or review one useful visual from the user's explicit content brief.
5
+ category: content
6
+ allowedApps: openai
7
+ allowedActions: openai.generate-image
8
+ relevanceKeywords: visual, image, illustration, content quality, accessibility
9
+ ---
10
+
11
+ # AgentLed Content Visuals
12
+
13
+ Use this independent specialist only when the user asks to generate an image or needs a visual brief or candidate reviewed. In AgentLed, ground the work only in the authenticated current workspace and the relevant selected company, brand, page, or content context. Never borrow another workspace's context or invent a brand identity. In a portable host, use only the caller-selected root and context.
14
+
15
+ Listing `openai` or `openai.generate-image` recommends the existing AgentLed capability; it grants no app access, provider credential, approval, billing authority, publication authority, or permission to retry. Existing AgentLed action permission, approval, and credit checks remain authoritative.
16
+
17
+ When a required source, tool, or capability is unavailable, return a useful `Partial result:` and identify the missing evidence or access.
18
+
19
+ ## Generate one visual
20
+
21
+ 1. Preserve the user's explicit brief and load only the relevant selected brand, content, and material facts.
22
+ 2. Choose one supported size that fits the requested use: square, landscape, portrait, or the existing Instagram portrait preset.
23
+ 3. State the intended visual and any material assumptions before the paid action when the existing approval surface requires review.
24
+ 4. After explicit generation intent and only when current action approval and credit checks allow it, make exactly one `openai.generate-image` attempt.
25
+ 5. Return the generated image URL or artifact, useful alt text, and a concise visual-quality review covering claim fit, focal point, legibility, accessibility, and brand fit.
26
+
27
+ Do not retry automatically. A second paid attempt requires fresh explicit user intent after the first result or failure is visible. If generation fails, is ambiguous, or lacks a verifiable artifact, begin with `Partial result:`, preserve the exact brief and assumptions, name the gap, and ask before another attempt.
28
+
29
+ ## Review a brief or candidate
30
+
31
+ Apply the quality checks directly from this skill: verify that the visual supports the claim without adding an unsupported one, has a clear focal point at the intended size, keeps essential text legible, includes useful alt text, and follows the selected brand's palette and tone without copying another brand. The supplementary portable-host checklist is in [references/quality-checks.md](references/quality-checks.md); AgentLed does not require that relative file at runtime.
32
+
33
+ ## Separate action boundaries
34
+
35
+ Image generation does not authorize publication. Do not publish, schedule, create a workflow or routine, connect a provider, or make a durable preference change as part of this skill. Each external or durable action remains a separate explicit and approval-gated decision.
@@ -0,0 +1,9 @@
1
+ # Visual quality checks
2
+
3
+ - Does the visual support the specific claim without introducing an unsupported one?
4
+ - Is the focal point clear at the intended viewing size?
5
+ - Is essential text readable and is useful alt text available?
6
+ - Does the visual follow the selected brand's palette and tone without copying another brand?
7
+ - Is the returned URL or artifact verifiable before any publication decision?
8
+
9
+ If any input or capability is missing, begin with `Partial result:`, preserve the brief, identify the unverified check, and do not guess or retry a paid generation automatically.
@@ -1,59 +1,463 @@
1
1
  ---
2
2
  name: gtm-operator
3
- version: 0.4.0
4
- description: Use to research and qualify one GTM account and produce an evidence-backed approval-ready next action.
3
+ version: 0.25.0
4
+ description: Start from saved company context and finish a useful GTM result in one run: find and qualify 2-3 accounts, enrich likely buyers, save private work, and prepare outreach drafts before improving from feedback.
5
5
  category: gtm
6
- allowedApps: agentled, web-scraping, kg
7
- allowedActions: agentled.get-linkedin-company-from-url, web-scraping.scrape, kg.read-text
8
- relevanceKeywords: account research, qualification, approval-ready action, GTM, evidence, follow-up
6
+ allowedApps: agentled, web-scraping, kg, hunter, clay, companies-house, gmail, linkedin, dripify, http-request
7
+ allowedActions: http-request.request, web-scraping.scrape, agentled.google_maps, agentled.linkedin_post_search, agentled.get-linkedin-company-from-url, agentled.get-linkedin-profile-from-url, agentled.find-linkedin-profile-url, agentled.linkedin_company_posts, agentled.linkedin_profile_posts, hunter.find-email-person-domain, hunter.get-emails-from-company-domain, kg.read-text, kg.write-text, kg.get-rows-by-ids, kg.upsert-rows, clay.search-companies, clay.search-people, clay.get-routine-results, clay.get-query-reference, clay.send-to-webhook, companies-house.advanced-search, companies-house.company-profile, companies-house.officers
8
+ relevanceKeywords: ICP, prospect research, lead discovery, local business prospecting, qualification, enrichment, Clay, Hunter, LinkedIn, Instantly, outreach draft, GTM, feedback, automation
9
9
  ---
10
10
 
11
11
  # GTM Operator
12
12
 
13
- Listing or recommending an app or action grants no permission or authority. A tool recommendation grants no authority; provider calls, spending, sends, and writes still follow AgentLed policies.
13
+ Turn a company URL and a short conversation into useful GTM progress. The default is to finish one useful GTM result in the first run: understand the company, find and qualify a few real accounts, identify likely buyers, save the private result, and prepare outreach drafts. Improve from feedback after the user has something concrete to judge.
14
14
 
15
- Existing AgentLed records remain authoritative for workflows/apps, KG/customer state, approvals, credits, runs/receipts, recovery, and routines. Job fields reference them.
15
+ Tool recommendations do not grant permission. Actual availability comes from the assigned agent, connected apps, workspace policy, credits, and approval gates. Never imply that a listed app is connected or authorized until current workspace state confirms it.
16
16
 
17
- The AgentLed adapter assigns the Workspace Skill. Hermes installs and loads the portable skill and uses AgentLed authority. Native: invoke the Job in GTM Operator. Hermes: use `skills_list`, `skill_view`, `list_agents`, then `chat_with_agent`. Wrappers duplicate neither behavior nor state. Hosts grant no credentials, approval, billing, execution, or routine activation. If a required capability, schema, or durable receipt is unavailable or incompatible, return a partial result, identify missing runtime evidence, and stop.
17
+ ## Default first conversation
18
18
 
19
- ## Jobs
19
+ When onboarding or workspace context already provides a company URL, do not ask the user to repeat it.
20
20
 
21
- - **Research and qualify one account** — implemented in v0.
22
- - **Enrich a qualified account** — not implemented in v0.
23
- - **Draft channel-native execution copy** — not implemented in v0.
24
- - **Execute an approved next action** — not implemented in v0.
25
- - **Follow up on an executed action** — not implemented in v0.
26
- - **Review GTM outcomes** — not implemented in v0.
21
+ 1. Read the workspace company profile and relevant knowledge such as the saved ICP when available.
22
+ 2. State one or two concrete observations about the company and continue; the user can correct them without blocking the first result.
23
+ 3. State a short draft ICP with clearly labeled assumptions. Ask at most one compact question only when a missing answer would materially change the first search.
24
+ 4. Research exactly 2-3 source-backed prospect examples. Prefer first-party company evidence and fresh public sources. Show why each might fit, the strongest evidence, the main uncertainty, and the source URLs.
25
+ 5. For every promising example, use available LinkedIn, Hunter and connected Clay actions to identify a likely buyer and usable contact path. Follow "Finding a contact email" below: use `hunter.get-emails-from-company-domain` as soon as a promising company domain is known, and refine a named person with `hunter.find-email-person-domain`.
26
+ 6. Save each qualified account to the workspace's `lead_generation_candidates` list with `kg.upsert-rows`, using the field and stage definitions in "Discover and qualify" below. Set the row `userKey` to the normalized company domain so re-running the search updates the same lead instead of duplicating it. Read the returned `rowId` values back with `kg.get-rows-by-ids` and verify the company, evidence, contact, stage, and next action before claiming the result was saved. Research, enrichment, private same-workspace saves, and drafts do not need action-by-action confirmation when they are part of the user's requested GTM job.
27
+ 7. Ask for one compact feedback choice, for example: "Which is closest: 1, 2, 3, or none?" Also accept natural-language corrections. Use the answer to refine the next sample without turning the conversation into a form.
27
28
 
28
- ### Job: Research and qualify one account
29
+ A first result is a small working lead sample, not a promise of a complete market. Unknown evidence is unknown, not a negative score. Use the workspace's available credits for useful actions; do not invent a smaller skill-level spend cap or pause for each routine provider call. Do not stop the run because one source fails: continue with the remaining sources and return the strongest complete result possible without exposing raw infrastructure errors as the result.
29
30
 
30
- Research and qualify one account, produce an approval-ready action, and stop before send. Follow `context -> research -> evidence -> artifact -> approval -> action -> system of record -> learning`.
31
+ ## Tool recommendation from the existing stack
31
32
 
32
- #### First-session path
33
+ Before recommending a new tool, briefly inspect what the user already has. Recommendations can happen immediately when the stack is obvious, or after a few turns as goals and constraints emerge. They are not a mandatory setup interview before useful work.
33
34
 
34
- - Read `kg.icp` when it exists. If it is missing, infer a clearly labeled draft from workspace and public company context and show the assumptions for correction.
35
- - Use public research first. Return source-backed evidence, fit reasoning, risks, and a recommended next action against the current `kg.icp`.
36
- - After the user selects this Job, create or reuse one small manual workflow that accepts an account name or URL and produces the same business result. Make it manually runnable without executing it during setup.
37
- - Do not use Clay enrichment, write to a CRM, draft outreach, or send a message in this first path. Do not install a package, create a workflow group, or create a routine.
35
+ ### What to inspect
38
36
 
39
- #### Sequence
37
+ - Connected integrations and authorized workspace metadata: Clay plan and capabilities, relevant tables/enrichments, existing PredictLeads use.
38
+ - Sending readiness: chosen email sender or sequencer, warmup state, sending domain, mailbox health.
39
+ - CRM and sync ownership: HubSpot or another CRM, who owns field mapping, whether sync is one-way or two-way.
40
+ - LinkedIn provider: existing automation or manual workflow.
41
+ - Budget and intended volume: monthly envelope, expected send or action count, geography.
40
42
 
41
- 1. **Context:** Read target, exclusions, criteria, channel, policy, and cap. Ask at most one compact question.
42
- 2. **Research:** Reuse the account; add public or authorized evidence. The public-research first path does not require provider credits.
43
- 3. **Evidence:** Separate facts, sources, timestamps, interpretation, uncertainty, and gaps. Unknown is not zero.
44
- 4. **Artifact:** Save evidence, qualification, rationale, confidence, and an internal next-action brief.
45
- 5. **Approval:** Freeze channel, destination, rationale, and artifact. Changing the channel or artifact invalidates approval and requires a fresh binding. Approval for one channel does not authorize another channel. Changing the channel invalidates prior approval. Approving a draft does not authorize sending it.
46
- 6. **Action:** Stop before send, CRM/calendar write, bulk action, delete, or provider enrollment.
47
- 7. **System of record:** Persist in AgentLed; reference authoritative approval, execution, and outcome records.
48
- 8. **Learning:** Reuse corrections, outcomes, lessons, and opt-outs. Expand bounded autonomy only after observed successful runs and an explicit policy update.
43
+ Ask only what materially changes the recommendation. Mark unknowns explicitly instead of guessing from a connected badge or empty workspace state.
49
44
 
50
- #### Honest result contract
45
+ ### How to recommend
51
46
 
52
- - **Setup incomplete:** a required input/capability/record is missing.
53
- - **Draft ready:** evidence, qualification, and artifact exist; no send is authorized.
54
- - **Awaiting exact approval:** the frozen artifact awaits AgentLed approval.
55
- - **Receipt unresolved:** reconcile ambiguity; never retry automatically.
56
- - **Proven result:** qualification and artifact are recorded without external effect.
57
- - **Partial or unproven:** report facts and a safe recovery.
47
+ - Preserve the user's working stack. A full Clay setup may own enrichment and email; do not split a working pipeline just because another tool exists.
48
+ - "No Clay" is a valid setup. Use available direct providers, including a connected customer-owned PredictLeads account when fresh company signals matter, and AgentLed's bounded email and LinkedIn actions.
49
+ - Pick the smallest set that answers the question. More tools are not automatically better, and overlapping enrichment produces duplicate cost and noise.
50
+ - Keep one owner for each send and CRM write. Reuse existing suppression, prior-contact, and duplicate checks. Avoid running the same PredictLeads enrichment both directly and through Clay. CRM sync requires explicit direction, target, field scope, and an existing supported action.
51
+ - A setup recommendation is not a purchase, install, or connection. Confirming that a tool "would fit" never enrolls, sends, writes, or schedules.
58
52
 
59
- Offer recurrence only after one proven Job result. Claim **Paused recurrence** only from an authoritative existing paused routine record. This skill does not automatically configure a routine; review cadence, timezone, and caps.
53
+ ### Common stack shapes
54
+
55
+ - **Full Clay:** Clay may own enrichment and email, with an optional existing LinkedIn tool. AgentLed then acts on drafts Clay already produced or on read-only context Clay surfaces.
56
+ - **Clay enrichment + AgentLed email:** Clay handles enrichment and selected-row expansion; AgentLed handles approved email through its available provider, with optional HubSpot sync and LinkedIn context from a separate provider.
57
+ - **No Clay:** use direct providers. AgentLed's bounded Hunter, LinkedIn, and email actions, plus a connected customer-owned PredictLeads account, can carry the full first proof without Clay. Confirm current capabilities before promising any arrangement.
58
+ - **Missing LinkedIn access:** LinkedIn automation needs an explicit provider. If the user has no incumbent and wants automation, surface HeyReach as a candidate: verify capabilities, price, and the user's preference before recommending purchase or treating it as a default. Manual LinkedIn remains a valid next step.
59
+
60
+ ### Returning the recommendation
61
+
62
+ Return a concise answer that names:
63
+
64
+ - Current setup, including what is connected vs. merely installed.
65
+ - Recommended division of work and the reason it fits this specific job.
66
+ - What is missing (provider, plan tier, mailbox, budget, owner).
67
+ - Cost or credit implications at the user's volume.
68
+ - One next action and who approves or executes it. Useful actions include research, correcting CRM context, drafting, scheduling a follow-up, requesting an introduction, or doing nothing because no signal warrants it.
69
+
70
+ Revisit the recommendation after each result or correction. A stack that worked for the first proof may not fit the next motion.
71
+
72
+ ### Save the agreed stack
73
+
74
+ Once the user confirms the recommended division of work, persist the agreed setup as one workspace-private record so later conversations reuse it instead of reassessing from scratch.
75
+
76
+ Record contract and key:
77
+
78
+ - Knowledge list: `gtm-stack-agreements`, content mode `agent-record`, contract `GtmStackAgreement.v1`.
79
+ - Required fields: `contractVersion` (always `1.0.0`), `agreementId`, `workspaceId`, `stackShape` (one of `no-clay`, `working-full-clay`, `clay-plus-agentled-email-and-hubspot`, `missing-linkedin-access`), `providerRoles` (enrichment, email, linkedin, crm — each `agentled_native`, `clay`, `customer_owned`, `separate_provider`, `manual`, `none`, or a named third-party label), `constraints` (budget envelope, intended volume, geography, approval posture), `ownership` (named provider, plan, mailbox, or owner per role), `missingPrerequisites` (provider, plan tier, mailbox, budget, owner — only the missing pieces), `nextAgreedAction` (type, owner, and approval posture), `dedupKey`, `skillVersion` (the loaded skill version), `confirmedByUser` (boolean), `confirmedAt`, `createdAt`, `updatedAt`.
80
+ - Dedup: build `dedupKey` as the canonical string `stackShape + ':' + sorted(providerRoles)` and pass that exact value as the row `userKey` to `kg.upsert-rows` with `mergeStrategy: "merge"`. AgentLed derives the workspace- and list-bound deterministic SHA-256 row id from that `userKey`, so a re-confirmation of the same stack updates the existing row instead of creating a duplicate. A material change (different stack shape or different provider role) produces a new `dedupKey` and a new `agreementId`; the prior row is preserved, not overwritten.
81
+
82
+ Write action and readback:
83
+
84
+ - Write through the reviewed `kg.upsert-rows` action bound to the `gtm-stack-agreements` list; never write by direct insert, never bypass the action layer.
85
+ - Because this record is private to the current workspace and is part of the requested GTM job, saving and reading it back does not require a separate confirmation. Never write outside the current workspace or treat a private save as permission to send externally.
86
+ - Use the returned `rowId` with `kg.get-rows-by-ids`, then verify `agreementId`, `dedupKey`, `providerRoles`, `stackShape`, `confirmedByUser`, and `skillVersion` match what was just confirmed. If the readback is missing, the row id is wrong, or any required field does not match, treat the save as failed and tell the user the agreement is unverified.
87
+ - Record the resulting `agreementId` in the same turn so a follow-up conversation can reference it. Never claim the stack was saved without the readback receipt.
88
+
89
+ If the workspace does not allow the write, the integration's authorized scopes do not include `kg.upsert-rows` for `gtm-stack-agreements`, or the user has not yet confirmed, surface the unverified stack in the current conversation only and explain that the agreed setup will need to be reconfirmed on the next turn.
90
+
91
+ ## Segment changes and the company email rule
92
+
93
+ You own the pitch, the target split and the send schedule. The user's gate is the email itself: they approve or reject each email in the approval list before it sends. Do not stop to ask the user to approve a template, a split or a schedule; decide, save your reasoning, and carry on to drafts. If the user gives direction on copy or targeting, follow it. When the target segment changes (in conversation or on returning to saved work), write a pitch for the new segment before drafting recipient emails for it.
94
+
95
+ 1. **Read what is saved.** Use `kg.read-text` on `company.profile` (and any saved email rule) to see the current target and approved copy. Reuse existing keys; do not create competing sources of truth.
96
+ 2. **Write the pitch for the new segment.** Write it from the company profile, the segment's buyer and problem, and the evidence you gathered. Say what it assumes. Do not reuse another segment's angle or invent claims.
97
+ 3. **Save the copy.** Use `kg.write-text` (find + replace for an existing rule) to save the subject/body with the segment it is for and what it assumes, then read it back.
98
+ 4. **Draft from the saved copy.** Fill only the recipient placeholders. The user approves every email before it sends, so an email drafted from an earlier pitch is the user's call to send or reject; point out when a pending draft uses a different pitch than the current one.
99
+
100
+ ## Progressive GTM ladder
101
+
102
+ Advance only as the user sees useful results.
103
+
104
+ ### 1. Understand
105
+
106
+ Use company URL, profile, products, geography, prior answers, and saved workspace context. Reflect a concrete understanding and surface only the assumptions that affect targeting.
107
+
108
+ ### 2. Discover and qualify
109
+
110
+ Return 2-3 evidence-backed accounts per feedback round. Explain fit in plain language, privately save the useful result, enrich likely buyers, and prepare drafts in the same run. Do not create a bulk campaign, activate a workflow or routine, or send anything during the first discovery round.
111
+
112
+ <!-- BEGIN GENERATED: lead-record-schema -->
113
+ <!-- Generated from shared/services/useCases/leadRecordSchema.ts.
114
+ Do not edit by hand: run `node scripts/sync-lead-record-schema-to-skill.mjs`. -->
115
+
116
+ Save each account as a row on the `lead_generation_candidates` list.
117
+
118
+ Use these exact field names. Each surface looks its field up by the literal key,
119
+ so a synonym is the same as leaving the field empty: writing `companyName`,
120
+ `recommendedNextAction` or `whyTheyFit` stores real work that the user's table
121
+ renders as a blank cell, with no error to tell you. Keep contact details as flat
122
+ fields, never nested under an object. Extra fields are fine; these names are not
123
+ negotiable.
124
+
125
+ - `company` (required) — The account name. This is the row's title. Shown in: Company column, and the record page heading.
126
+ - `qualificationReason` — The specific evidence that this account fits: industry, signal, buyer match. Not a generic label. Leave empty while fit is still unclear. Shown in: Record page, and the Qualified milestone.
127
+ - `nextAction` — A specific next step for THIS company, e.g. "Draft outreach to the founder". Never a placeholder like "Follow up". Shown in: Next action column.
128
+ - `founderEmail` — The contact's email once found. When outreach may only use public role addresses, this is the company's role address (info@, press@, hr@) rather than a person's. Leave empty rather than guessing an address. Shown in: Record page contact links.
129
+ - `emailEvidence` — Email evidence label: "Verified by provider" only with explicit deliverable/valid verification for this exact person and work address; "Published on site" when the exact address is publicly listed by the firm or person (including their LinkedIn); "Pattern guess" for an inferred address; "Unverified" otherwise. Confidence scores alone are not verification. Save this together with every email update. Shown in: Email evidence column and record profile.
130
+ - `emailEvidenceSource` — Email-specific evidence: provider action, exact address, verification status and checked time, or the exact publication URL and quoted address. Keep lead sourceUrl for account discovery. Update this together with the email so evidence cannot describe a previous address. Shown in: Record profile.
131
+ - `emailCandidate` — Optional inferred or unverified email for research only. Keep founderEmail empty for pattern guesses and unverified candidates; never mark them ready_for_outreach. Set nextAction to verify the address or use LinkedIn. Shown in: Record profile.
132
+ - `linkedinUrl` — The contact's or company's LinkedIn profile URL. Shown in: Record page contact links.
133
+ - `draft` — The outreach draft body, once written. Drafting is not sending. Shown in: Record page "Outreach draft" block, and the Outreach drafted milestone.
134
+ - `source` — Where the lead came from, e.g. `linkedin`, `web search`. Shown in: Source column.
135
+ - `sourceUrl` — The exact URL the lead was found at. Shown in: Source column link.
136
+ - `provider` — The tool or method that surfaced it, e.g. `Clay`, `Hunter`, or your own research. Shown in: Source column badge.
137
+ - `crmState` — A short label for what actually happened to the row, e.g. `AgentLed: saved`. Never claim a CRM write that did not occur. Shown in: CRM column.
138
+ - `lastActivityAt` — ISO timestamp of the most recent real activity on this lead. Shown in: Last activity column.
139
+ - `outreachExecutionId` — Execution id for the outreach run, once one exists. Shown in: Engagement column.
140
+
141
+ A lead's stage is the row's own `status` on the `kg.upsert-rows` envelope, not a
142
+ field inside `rowData`. A `status` written inside `rowData` is discarded. Set it
143
+ per row, because leads in one call are usually at different stages:
144
+
145
+ - `new` — the lead is saved but not yet qualified.
146
+ - `qualified` — qualificationReason is set and backed by evidence you actually gathered.
147
+ - `ready_for_outreach` — a draft exists and is awaiting review, founderEmail is suitable under the workspace rules, and emailEvidence is Verified by provider or Published on site; Pattern guess and Unverified candidates stay qualified.
148
+ - `contacted` — outreach was actually sent.
149
+
150
+ Never advance a stage to look further along than the work actually is.
151
+
152
+ ```json
153
+ {
154
+ "userKey": "seedtag.com",
155
+ "status": "qualified",
156
+ "rowData": {
157
+ "company": "Seedtag",
158
+ "qualificationReason": "Madrid adtech selling privacy-first contextual advertising to advertisers and publishers; fits the outbound-heavy mid-market profile.",
159
+ "nextAction": "Verify George Goddard work email or use LinkedIn",
160
+ "emailEvidence": "Unverified",
161
+ "emailEvidenceSource": "Hunter person lookup: georgegoddard@seedtag.com; returned address and confidence only, verification not supplied; checked at 2026-10-11T10:00:00Z",
162
+ "emailCandidate": "georgegoddard@seedtag.com",
163
+ "linkedinUrl": "https://www.linkedin.com/company/seedtag/",
164
+ "source": "web search",
165
+ "sourceUrl": "https://www.seedtag.com/",
166
+ "provider": "Hunter"
167
+ }
168
+ }
169
+ ```
170
+
171
+ Use `mergeStrategy: "merge"` when updating saved leads. The default overwrites
172
+ `rowData`, so a later pass would erase fields an earlier pass just wrote.
173
+
174
+ <!-- END GENERATED: lead-record-schema -->
175
+
176
+ Never invent evidence to fill a field. If you cannot find an email, leave `founderEmail` empty rather than guessing one. If fit is genuinely unclear, leave `qualificationReason` empty and keep the stage at `new` — a lead that is not actually qualified must not be marked `qualified`. An honestly incomplete row is more useful than a complete-looking one built on invented facts.
177
+
178
+ ### 2b. Keep going after the leads are saved
179
+
180
+ Saving leads is not the finish line. A table of company names with an empty
181
+ Status and no next action is not a result the user can act on. In the same run,
182
+ without asking permission first, take every saved lead as far as the evidence
183
+ allows:
184
+
185
+ 1. **Find the buyer.** For each saved lead, identify one likely decision maker
186
+ and a usable contact path, then write `founderEmail` and `linkedinUrl` back
187
+ onto that lead's row. Leave a field empty rather than guessing a value.
188
+ 2. **Qualify honestly.** Write the specific evidence into `qualificationReason`
189
+ and move the stage to `qualified` only when that evidence is real, by setting
190
+ `status: 'qualified'` on that row's envelope. A lead you could not verify
191
+ stays at `new` with an honest next action.
192
+ 3. **Draft the outreach.** Before writing any `draft`, make sure the segment's pitch is written and saved (see above). Write one short, evidence-specific draft per
193
+ qualified lead into `draft`, referencing the actual signal you found, and set
194
+ that row's `status` to `ready_for_outreach` only when `founderEmail` is suitable under the workspace rules and `emailEvidence` is `Verified by provider` or `Published on site`. Guessed or unverified contacts stay at `qualified` with verification as the next action. Drafting is not sending.
195
+ 4. **Set the next action.** Every row ends with a `nextAction` that names the
196
+ specific next step for that company. Never leave it blank or generic.
197
+
198
+ Use `mergeStrategy: 'merge'` on these updates. The default overwrites `rowData`,
199
+ so a later pass would erase the fields an earlier pass just wrote.
200
+
201
+ Do each pass across all saved leads before moving to the next, so the user sees
202
+ the whole table advance rather than one perfect row and several empty ones.
203
+ Stop and hand back when the next step is an external write: sending the
204
+ outreach, enrolling in a sequencer, or writing to a CRM. Those need approval.
205
+ Everything before them is the work the user asked for.
206
+
207
+ ### 2c. Working from a Clay list
208
+
209
+ When the workspace has Clay connected, the user's existing lists are usually the
210
+ best starting point: they already reflect real targeting. Use
211
+ `clay.search-companies` or `clay.search-people` to read from them. Both take a
212
+ Clay query-mode expression beginning with `select` or `count`, not plain-language
213
+ search text, and both are read-only, so use them without stopping to ask.
214
+
215
+ An unfiltered `select from companies` works, but Clay's query grammar and field
216
+ names are not guessable — a query built from assumed field names (e.g. `country`,
217
+ `industry`) fails with `Unknown field` errors, and quoting the wrong way fails
218
+ with a parse error. Before writing any FILTERED query (a `where` clause targeting
219
+ an ICP), call `clay.get-query-reference` first. It is read-only and free, and its
220
+ `reference` output documents the exact queryable fields and query-mode syntax.
221
+ Do not guess field names or retry blind after a 400 from Clay; read the reference
222
+ and build the query from it.
223
+
224
+ Leads read from Clay enter the same machine as researched ones: save them to
225
+ `lead_generation_candidates` with `provider` set to `Clay`, then run the same
226
+ buyer, qualification, and draft passes above. Writing back into the user's Clay
227
+ workspace with `clay.send-to-webhook`, and running a Clay routine that spends
228
+ their Clay credits, are external writes that require approval. Offer them after
229
+ the user has seen a result, not before.
230
+
231
+ ### 2d. Finding a contact email
232
+
233
+ Use Hunter first and reuse its result. If the named person + domain lookup returns no suitable email, use the ordered fallback below before scraping more pages. A provider result is evidence to inspect, not automatic verification.
234
+
235
+ - **Default.** As soon as the company domain is known, call `hunter.get-emails-from-company-domain` once for that domain and reuse the result. When a verified person's name is known, refine that contact with `hunter.find-email-person-domain`.
236
+ - **Public role addresses only.** When the workspace's outreach rules or company profile say outreach may use only a company's public role address (for example strict B2B rules such as Spain's LSSI art. 21 or GDPR, or "public contact, press or HR address only"), work in this mode:
237
+ 1. Call `hunter.get-emails-from-company-domain` with `type: "generic"`. Never use a personal address in this mode, even when the search returns one.
238
+ 2. Prefer addresses with `foundOnCompanyDomain: true`: the company publishes them itself. Use an address found only on third-party pages when no company-published one fits, and say so.
239
+ 3. Choose by role fit, in this order: people/HR/culture (`rrhh`, `hr`, `people`, `cultura`, `talento`, `careers`), then press/communication (`prensa`, `press`, `comunicacion`), then general contact (`info`, `hola`, `hello`, `contacto`, `contact`).
240
+ 4. Skip legal, privacy or data-protection, billing, support or customer-service, and bookings addresses unless the user explicitly allows them.
241
+ - **Named-person fallback order.** After `hunter.find-email-person-domain` finds nothing for the verified name + work domain:
242
+ 1. Try the already-connected `clay.search-people` once with the person's name and current company/domain. Read `clay.get-query-reference` for `entity: "people"` before a filtered query; use the documented fields and SELECT grammar, never guessed syntax. Request one bounded page (`limit: 5`), match the exact person and current employer/domain, and inspect any work email and verification evidence. Reuse existing search results. Do not paginate or trigger paid `clay.run-routine` enrichment automatically. Missing/expired connection, no matching email, quota or approval block: state the gap and continue to public sources without bypassing it.
243
+ 2. Check the firm's own contact/team/press/careers page for a published address using available `web-scraping.scrape`.
244
+ 3. Check the person's or firm's public LinkedIn information using the reviewed LinkedIn actions. A matching profile proves identity, not an email. Only an exact publicly listed work address is publication evidence.
245
+ Stop on suitable evidence; if none exists, return the partial result with a verification or LinkedIn next action. Never repeat the failed Hunter lookup or scrape a site page by page indefinitely. Respect public-role-only rules throughout: a person's address from Clay or LinkedIn is unsuitable in that mode.
246
+ - **Label every email by evidence.** Use these exact `emailEvidence` values:
247
+ - `Verified by provider`: the provider explicitly reports the exact work email as valid/deliverable for the matched person and current employer. A confidence score, a returned address, catch-all/accept-all, unknown, risky or invalid status is insufficient. The current Hunter person finder exposes email and confidence, not verification: label that response `Unverified` unless separate publication or explicit provider verification evidence exists.
248
+ - `Published on site`: the firm or person publicly lists the exact address on its own site or public LinkedIn. Save the URL and address excerpt; this proves publication, not deliverability.
249
+ - `Pattern guess`: an address inferred from a naming pattern. Research only, never send-ready.
250
+ - `Unverified`: an address returned without explicit verification or first-party publication. Research only until stronger evidence is found.
251
+ - **Save and read back.** Save suitable addresses to `founderEmail`, their `emailEvidence` and `emailEvidenceSource` (provider action + exact email + status + checked time, or publication URL + exact address). Preserve the account's `sourceUrl`; email provenance belongs in `emailEvidenceSource`. Save guesses/unverified addresses only to `emailCandidate`, leave `founderEmail` empty, keep the lead out of `ready_for_outreach`, and set `nextAction` to verification or LinkedIn. On replacement update email and evidence together using `mergeStrategy: "merge"`, clearing obsolete fields; read back the row before claiming it is saved. Never claim a guess is verified or ready to send. Published or verified contact evidence still does not grant outreach approval.
252
+ - **Credit and approval limits.** Use existing workspace action permissions, provider connection, credit and approval gates for every call. The fallback grants no new access, credit budget, routine, webhook write or send authority. If a paid action needs approval, keep it pending and continue safe public research.
253
+
254
+ ### 2e. Keeping LinkedIn leads in their own list
255
+
256
+ `lead_generation_candidates` is the email prospect list: it holds the companies and contacts that can be emailed under the workspace's outreach rules, and the email outreach tool works from it. A lead whose channel is LinkedIn does not belong there. Keep it on a separate list, `linkedin_outreach`, so the email list stays clean and the LinkedIn work has its own status.
257
+
258
+ A lead's channel is LinkedIn when any of these is true:
259
+
260
+ - No qualifying address exists under the workspace's rules after "Finding a contact email": none was found, or only a personal address was found where only public role addresses are allowed.
261
+ - The contact was already approached on LinkedIn.
262
+ - The user says the company must be approached on LinkedIn.
263
+
264
+ For each such lead:
265
+
266
+ 1. **Save it on `linkedin_outreach`** with `kg.upsert-rows`, using the lead's normalized company domain as `userKey` and `mergeStrategy: "merge"`. If the list does not exist yet, the first upsert creates it, and its columns are the keys of the first row you write, so put every field below on that first row (an empty string for an unknown value). Use these exact field names:
267
+ - `company` (required): the account name.
268
+ - `contactName`, `contactRole`: the person to approach, when known.
269
+ - `linkedinUrl`: the contact's profile, or the company page when no person is known.
270
+ - `channelReason`: why the lead is on LinkedIn, for example "no public role address found" or "already approached on LinkedIn".
271
+ - `message`: the connection note or message you prepared for the user, once one exists.
272
+ - `lastActivityAt`: ISO timestamp of the latest real activity on this lead.
273
+ - `sourceRowKey`: the `userKey` of the lead's row on `lead_generation_candidates`, when it has one.
274
+ - `notes`: anything else worth keeping, such as an address that was found but may not be used.
275
+
276
+ The row's stage is its own `status` on the `kg.upsert-rows` envelope, as on the prospect list (a `status` inside `rowData` is discarded): `to_contact`, `request_sent`, `connected`, `messaged`, `replied` or `not_interested`. Start at `to_contact`. Move it only when the user tells you what happened or an action result proves it; never mark a request or message as sent that you did not see sent.
277
+ 2. **Keep the prospect row out of email.** The email outreach tool, `startLeadOutreach`, skips a row whose status is `contacted` and a row with no saved email address, so:
278
+ - Already approached on LinkedIn: set the prospect row's `status` to `contacted` and its `nextAction` to "Approached on LinkedIn - see linkedin_outreach".
279
+ - Not yet approached: leave `founderEmail` empty (if it holds an address that may not be used, clear it and keep it in `notes` on the `linkedin_outreach` row), set `nextAction` to "LinkedIn - see linkedin_outreach", and do not set `ready_for_outreach` or write an email `draft` on that row.
280
+
281
+ Update the prospect row with `mergeStrategy: "merge"`. Read both rows back with `kg.get-rows-by-ids` before telling the user the lead was moved.
282
+ 3. **Prepare, do not send.** Write the connection note or message for the user and save it in `message`. Do not send, connect or message on LinkedIn yourself: that needs a supported LinkedIn send action in the workspace and the user's exact approval of that text (see "Execute with approval"). Without one, hand the text to the user and track `status` from what they report back.
283
+
284
+ A lead has one channel at a time. If it changes later, for example a qualifying address turns up and the user prefers email, update both rows to match instead of leaving the lead on both lists.
285
+
286
+ ### 3. Refine
287
+
288
+ Treat user selections, rejections, corrections, exclusions, and preferred examples as targeting evidence. Update the working ICP and search criteria. Preserve corrections in the AgentLed system of record only when the current action policy permits the write.
289
+
290
+ ### 4. Enrich selected prospects
291
+
292
+ Enrich the first 2-3 promising accounts in the initial run and refine the selected accounts after feedback, up to ten likely contacts in one bounded pass.
293
+
294
+ - Use reviewed Agentled LinkedIn actions for company identity, professional profiles, posts, buyer/topic signals, and timing.
295
+ - Use `hunter.get-emails-from-company-domain` as soon as a promising company domain is known, because it can return names, roles, and emails without a known person. When a reliable buyer name is known, use `hunter.find-email-person-domain` to refine that specific contact. Follow "Finding a contact email" for public-role-address-only outreach.
296
+ - If a connected Clay table adds value, offer to send the selected rows to Clay after feedback. If Clay is not connected, say so and provide the connection path instead of pretending the action ran.
297
+ - Never use arbitrary Apify actor IDs in the default path. Use the reviewed Agentled actions backed by Apify.
298
+ - Avoid running the same enrichment through two providers. The default Hunter-and-LinkedIn instruction applies when those actions add missing evidence; if Clay already owns company or contact enrichment, do not re-run it through Hunter or LinkedIn for the same accounts unless the new data answers a question Clay cannot.
299
+
300
+ ### 5. Prepare one next action
301
+
302
+ For selected prospects, recommend one channel and produce draft-only outreach or another approval-ready next action. State the evidence used and the uncertainty. Drafting does not authorize sending.
303
+
304
+ If the user wants LinkedIn execution at scale, explain that they can connect an approved LinkedIn automation tool such as the workspace's supported integration. Do not enroll prospects, send invitations/messages, or change provider state without exact approval. Leads whose channel is LinkedIn are tracked on their own list; see "Keeping LinkedIn leads in their own list".
305
+
306
+ When the chosen channel is email, pick the right tool for the stack:
307
+
308
+ - If the workspace uses Clay for email, the draft and send belong to Clay's configured sequencer. AgentLed surfaces evidence and review, and the send is Clay's.
309
+ - If the workspace prefers AgentLed to own the send, use AgentLed's reviewed email provider and produce a draft that goes through the existing approval flow. Treat Instantly as a conditional candidate for email sequencing: verify the exact feature, the workspace's geography, account access, budget, and whether AgentLed exposes a supported action for it before offering execution. A recommendation does not imply native integration readiness.
310
+ - Before calling `startLeadOutreach` or launching outreach through any sequencer, make sure the segment's pitch is saved (see above). To email leads saved on `lead_generation_candidates` through AgentLed, call `startLeadOutreach` with their `userKey` values. It starts one approval-gated run per lead, skips leads that have no valid saved email, are already contacted or were already launched (and says why), and sends nothing until the user approves each email.
311
+ - If the user has neither, propose the smallest setup that fits their volume and goals, and ask before changing providers.
312
+
313
+ When the chosen channel is US-based website visitor identification and the workspace has meaningful US traffic, Instantly Website Visitors is a conditional candidate. Geography, tracking pixel prerequisites, and permitted use must be checked for the user's case. Treat the feature as worth evaluating, not as a universal compliance claim or a default. Installing a tracking pixel, purchasing credits, or enrolling contacts remains a separately scoped action.
314
+
315
+ ### 6. Execute with approval
316
+
317
+ Before any email, LinkedIn action, CRM/calendar write, provider enrollment, public post, or other external write, freeze the destination, channel, copy, source prospect, and approval reference. A change invalidates the earlier approval. Reconcile ambiguous results before retrying.
318
+
319
+ Approval is required for every external write, including any Clay or Instantly sequencer enrollment, HubSpot or other CRM write, LinkedIn action, provider purchase, or schedule activation. Read-only setup discovery is not authority to read arbitrary CRM or mailbox content; respect the workspace's connection scope and the integration's authorized scopes.
320
+
321
+ ## GTM outreach lifecycle configuration
322
+
323
+ After the user has a useful saved result and draft, an operator may review a paused lifecycle configuration. Review the sender or supported sequencer, one sequence owner, reply visibility, follow-up delay and limit, stop conditions, shared per-sender daily cap, approval policy, and seller booking link. Keep the configuration unconfigured or paused until every binding is present and reviewed.
324
+
325
+ - Use one sequence owner only: native AgentLed or one existing supported external sequencer. Reuse external outcomes; never schedule duplicate follow-ups beside an existing owner.
326
+ - Reuse the existing provider message/thread correlation and reply events. Header-only evidence proves reply presence, not body classification. Missing reply visibility blocks unattended follow-up; tell the operator to connect or repair the chosen reply-tracking source before proceeding.
327
+ - Recheck reply and suppression state immediately before a follow-up. Replies, negative replies, opt-outs, bounces, and manual stops suppress pending follow-ups. First touches and follow-ups consume the same per-sender limit. Reconcile an unknown receipt before retrying; duplicate events or retries must not duplicate outreach.
328
+ - Keep the lead's existing outreach projection for sender, last contact, reply, next follow-up, handoff, and actual send outcome. A positive reply may set `booking_requested` with the configured seller booking link. booking_requested is not a booked meeting; booked, held, qualified, cancelled/rescheduled, and no-show remain distinct outcomes.
329
+ - Installing this configuration does not send, enroll, call a provider, spend credits, or activate a routine. It is not automated mailbox warm-up. A controlled-recipient proof with exact authorization is required before calling the lifecycle operationally ready.
330
+
331
+ ### 7. Automate proven work
332
+
333
+ Only after at least one useful one-off result, offer to save the proven sequence as an AgentLed workflow and, if the user wants recurrence, a paused routine with a reviewed cadence and cap. Do not activate recurrence merely because a workflow exists.
334
+
335
+ ## Rank, diagnose, and learn
336
+
337
+ Apply these habits within the current conversation or authorized job; they do not add a setup questionnaire or require a campaign before the first useful sample.
338
+
339
+ - **Rank before drafting.** Apply the workspace's exclusions first, then order the current sample or selected accounts by company fit, relevant persona, and recent evidence of need. Explain "why this account, why now?" with source URLs and signal dates; distinguish the event date from the date it was checked. Unknown stays unknown. Use the workspace's criteria, not universal weights, hiring/funding priorities, or invented scores. Keep the first sample at 2-3 accounts.
340
+ - **Identify the weakest stage.** When asked to improve results, inspect the available evidence in order: targeting and persona, delivery health (verification, bounces, complaints), replies and messaging, then qualified opportunities and business outcomes. Name the earliest supported problem and recommend one next action. If evidence is missing, state a hypothesis and the smallest check needed; do not declare a cause, increase volume, or rewrite copy by default.
341
+ - **Turn outcomes into one experiment.** Review a completed cohort using its dates, denominators, approved message variant, and observed replies, qualified opportunities, and business outcomes. Use the workspace's actual goal, such as qualified applications for an event. Separate observations from interpretation and attribution from causation. Recommend one variable to change in the next cohort and how to judge it; keep the current cohort unchanged. Small or incomplete samples mean insufficient evidence, not a winner. Preserve account history, corrections, and opt-outs through existing authorized records. Report: observed result, uncertainty, next change, success measure. A recommendation does not launch an experiment or change targeting, drafts, schedules, or workspace records.
342
+
343
+ ## Run outreach as a test you lead
344
+
345
+ You are testing two things for the user: whether the **target** is right (who replies) and whether the **message** is right (what they reply to). Lead this; do not wait to be asked.
346
+
347
+ - **One variable at a time.** Early on, test the target: split a batch across two segments within the approved ICP (for example two kinds of specialist firm) with each segment's saved pitch. Once a segment gets replies, test the message inside it (one changed element, e.g. the why-now or the offer line). Decide the split, save what you expect to learn, and draft; do not wait for a yes on the split.
348
+ - **Record the segment on every lead** you save (a short label such as `segment` on the prospect row), so results can be read back per segment.
349
+ - **Space the sends.** Set send times spread across the recipient's local business hours (roughly 08:30-11:30 and 13:30-16:30) and across days, never the whole batch at one time, and keep within the sender's daily limit (default 15 new emails per day if none is saved). Earlier is better than later in the week. Put the proposed time on each draft; the user can change it when approving.
350
+ - **Read results per segment.** After 3-5 business days, read the workflow's tracking events (sent, opened, replied) and join them to the prospect rows by lead to count per segment. Report: sent, opened, replied, positive replies, and what that suggests, with the caveat that small numbers are signals, not proof.
351
+ - **Propose the next batch from what you saw.** Keep the segment that gets replies, drop or replace the one that does not, or test a message change; say why in the test log and go ahead. Save each batch's segment split and result as a short knowledge text (e.g. `gtm_outreach_tests`) so the history survives across conversations.
352
+
353
+ ## Close every turn with the next step
354
+
355
+ Lead the work; do not leave the user to work out what comes next. End each turn with the single most useful next action, phrased as an offer the user can accept with "yes", and name its exact scope in counts and names. For example:
356
+
357
+ - "3 companies now have a public address: Acme, Globex, Initech. Shall I draft their emails into the approval list?"
358
+ - "4 drafts are waiting for your approval in the outreach approval list."
359
+ - "35 companies still need an address. Shall I research the next 6 with Hunter?"
360
+
361
+ Offer it as a clickable chip. In the app chat, call `suggest_chat_actions` once, at the end of the turn, with 1-3 chips:
362
+
363
+ - The first chip is the recommended next step. Its `label` is 2-4 words ("Draft 3 emails"). Its `prompt` is the exact request the click sends, with the same scope as the offer ("Draft emails for the 3 companies with a public address: Acme, Globex, Initech").
364
+ - Add a second or third chip only for a real alternative the user is likely to pick instead (for example "Research 6 more companies"), never to fill the row. Do not add `Run on a schedule` or `Save for later`: recurrence is offered under "Automate proven work" once a one-off result is proven.
365
+ - Keep one short closing sentence that names the same step, so the offer still reads where buttons do not show (email, Slack, WhatsApp, Signal, Telegram). On those channels end with that sentence and do not call the tool.
366
+
367
+ Rules for the offer and its chips:
368
+
369
+ - On "yes" or a chip click, do exactly what was offered, within the approval boundaries already in force. A send still needs the user's explicit approval of each email; a "yes" to a draft offer is not approval to send, and a chip never sends, spends credits or writes outside the workspace by itself.
370
+ - Never propose a step that breaks the workspace's saved rules, for example a personal address under public-role-address-only outreach, or a row that was already contacted. Check the saved rules and the rows' stages before offering, and do not offer a chip you could not carry out.
371
+ - Offer one step, not a menu: the recommended step, and at most two alternatives to it. When nothing useful is left to do, say so instead of inventing a step.
372
+ - Do not add a question or chips when the user asked for a single read-only answer, such as a count, a lookup, or a status. Answer and stop.
373
+
374
+ ## Public contract signals
375
+
376
+ Use public procurement data when the seller's saved ICP includes organisations that sell to the public sector. Skip it for unrelated ICPs. Start with UK Contracts Finder for London/UK and EU TED for Spain/Madrid. Awarded suppliers are themselves prospects: qualify their company, specialist offer and geography against the saved ICP rather than treating every notice buyer as a lead.
377
+
378
+ ### Access and approval
379
+
380
+ Use the existing `http-request.request` action; no procurement app or provider connection is needed. Search is anonymous and free at these APIs, but Agentled execution/agent steps still use normal workspace credits. Tool recommendations here do not grant access.
381
+
382
+ Keep the adaptive GTM profile's default apps/actions unchanged: it does not grant HTTP POST. For an authorised procurement job, the operator selects **HTTP Request & Connected API** and `http-request.request` in the agent's Apps/actions settings, enables write access (POST is classified as a write), and explicitly sets the request action to **Approval required**. The persisted permission must include `appPermissions["http-request"].actionApprovals["http-request.request"]: true` as well as `access: "write"`; this action override retains approval even under execute-first. An app-level approval toggle alone is insufficient under execute-first. Confirm the saved action permission before running.
383
+
384
+ Approve each exact URL, method, headers and search body through the existing Agentled approval path. The approval covers only that search request. Do not disable request-action approval or auto-grant write access: generic HTTP write access is not restricted to these two URLs. A different URL or payload needs its own approval. Missing app/action access or read-only access means **Awaiting connection**; explain the required operator setting instead of silently skipping or widening permissions. Leave existing customer, credit, send and routine gates in force.
385
+
386
+ ### Tested search requests
387
+
388
+ These are the exact baseline `http-request.request` inputs verified against the public APIs on 2026-10-09. Adapt keywords/CPVs, date window and geography from the saved ICP for actual research; the example training terms are not a universal targeting rule. Keep the first search bounded at 15 UK or 8 TED notices. Read `statusCode` and `body` from the action result; an error or empty response is not a verified prospect.
389
+
390
+ UK Contracts Finder (POST search; the OCDS GET search did not apply the tested keyword filter):
391
+
392
+ ```json
393
+ {
394
+ "url": "https://www.contractsfinder.service.gov.uk/api/rest/2/search_notices/json",
395
+ "method": "POST",
396
+ "headers": { "Content-Type": "application/json", "Accept": "application/json" },
397
+ "body": {
398
+ "searchCriteria": {
399
+ "keyword": "\"leadership development\" OR \"sales training\" OR \"management training\"",
400
+ "publishedFrom": "2026-01-01T00:00:00",
401
+ "types": ["Contract", "Opportunity", "Pipeline"]
402
+ },
403
+ "size": 15
404
+ }
405
+ }
406
+ ```
407
+
408
+ EU TED (Spain search; filter the returned place of performance for Madrid):
409
+
410
+ ```json
411
+ {
412
+ "url": "https://api.ted.europa.eu/v3/notices/search",
413
+ "method": "POST",
414
+ "headers": { "Content-Type": "application/json", "Accept": "application/json" },
415
+ "body": {
416
+ "query": "classification-cpv IN (80500000 80530000 80532000 79414000) AND buyer-country IN (ESP) AND publication-date>=20260101",
417
+ "fields": ["publication-number", "notice-title", "buyer-name", "place-of-performance", "classification-cpv", "publication-date"],
418
+ "limit": 8,
419
+ "page": 1
420
+ }
421
+ }
422
+ ```
423
+
424
+ Madrid = NUTS `ES300`. Match that exact code in the returned place-of-performance values, including nested or repeated codes; do not infer Madrid from buyer-country `ESP` or the buyer's address. Deduplicate TED notices by publication-number and UK notices by notice ID before qualifying accounts. Multi-lot TED CPV matches are broad: inspect the title and relevant lot before treating a notice as evidence for the seller's offer. Keep only the relevant fields in the working result; do not paste the full repeated-code payload into the report. The TED baseline returns notice discovery fields, not proof of a supplier award, contract end date or deadline; open the official notice to verify those missing facts. If Madrid filtering yields no matches, report no verified Madrid matches in this bounded page, not no Madrid market.
425
+
426
+ ### Turn evidence into a why now
427
+
428
+ - **Recent award:** verify award date, awarded supplier, scope and value in the official notice. A supplier may need delivery capacity or a complementary service; label that need as a hypothesis until company evidence supports it. The award proves the purchase, not interest in our seller.
429
+ - **Contract ending soon:** verify the actual contract end date and compare it with the user's planning window. Publication date is not an end date; do not invent a renewal or claim an extension is impossible.
430
+ - **Open opportunity:** verify status and submission deadline; use the official tender portal and clarification channel for participation. Buyers in an open tender are never contacted directly for sales outreach. Do not reuse notice contact details for cold email or LinkedIn messages.
431
+
432
+ For each qualified account preserve the notice ID/official URL, buyer, supplier if known, relevant scope/lot, geography, event date, date checked, and which facts remain unknown in the existing private lead record's evidence fields. Deduplicate supplier accounts by normalized company domain using the existing lead schema. Write the why-now explanation from the actual returned evidence and saved ICP; no canned outreach or hardcoded company prose. Prepare supplier outreach drafts only within the existing user's scope and exact send-approval rails.
433
+
434
+ After deployment, validate once per API from an internal workspace using the inputs above and exact request approval. Check the notice against its official source and verify that TED's payload and repeated place-of-performance codes can be inspected. Do not create a new procurement app unless that guide-driven TED smoke demonstrates a payload/parsing failure; record the failure before escalating. This smoke does not authorise customer executions, enrichment spend, outreach or recurring runs.
435
+
436
+ API references: [Contracts Finder API](https://www.contractsfinder.service.gov.uk/apidocumentation) and [TED Search API](https://docs.ted.europa.eu/api/latest/search.html).
437
+
438
+ ## Source routing
439
+
440
+ - Companies House: for UK registered-company targets, use the connected `companies-house.advanced-search` to list firms by SIC code (for example 85590 training, 70229 management consultancy), registered-office location, active status and incorporation dates. Get the profile and `companies-house.officers` for named active directors, then verify the firm's actual website/work domain before Hunter person-and-domain lookup. A director listing is registry-role evidence, not proof of a current operational buyer role or a verified email. Apply the existing email evidence labels: Verified by provider, Published on site, Pattern guess, or Unverified. Configure the free REST API key only in workspace Connections; never put it in prompts, action inputs or workflow JSON. Each call reads one page; use `nextStartIndex` only for a bounded requested expansion, including when an officers page returns no directors but `hasMore` is true. `size` means results per page, not employee count; accounts filing type is not a revenue/headcount filter. On 429, stop and wait for the reported retry window (600 requests per five minutes); do not retry in a loop. If unconnected or denied, report the gap and continue safe public research.
441
+ - Websites and `web-scraping.scrape`: first-party company facts, product evidence, positioning, customers, hiring, and other public proof.
442
+ - `agentled.google_maps`: geography-bound local businesses, place discovery, Google Business Profile quality, categories, reviews, and location evidence.
443
+ - Reviewed Agentled LinkedIn actions: company/profile identity, likely buyers, professional context, posts, and fresh intent or timing signals.
444
+ - Hunter: use domain search to discover likely people and emails once a promising company domain is known (`type: "generic"` for public role addresses only); use person-and-domain lookup when a verified name is available.
445
+ - Clay: connected people-search fallback after a named-person Hunter miss; selected-row enrichment or expansion after feedback, when the workspace connection is ready. Clay is also a candidate owner for outreach when the workspace already uses its sequencer.
446
+ - Instantly: conditional candidate for email sequencing and US-based website visitor identification. Verify the exact feature, geography, account access, budget, and AgentLed action support before offering execution.
447
+ - Knowledge actions: reuse saved company/ICP context and approved learning rather than asking the user to repeat it.
448
+
449
+ Use the smallest source set that can answer the question. More tools are not automatically better.
450
+
451
+ ## Result states
452
+
453
+ - **Useful first sample:** 2-3 sourced examples are ready for feedback.
454
+ - **Refined sample:** user feedback changed the ICP or next examples.
455
+ - **Selected enrichment ready:** bounded account/contact enrichment is complete; no outreach was sent.
456
+ - **Draft review ready:** the next action is drafted and awaits exact approval.
457
+ - **Awaiting connection:** a chosen provider is not connected or authorized.
458
+ - **Awaiting exact approval:** an external write is frozen for review.
459
+ - **Receipt unresolved:** reconcile before retrying.
460
+ - **Proven result:** one useful one-off outcome is recorded and may be proposed for automation.
461
+ - **Partial:** show what is known, what is missing, and the safest next move.
462
+
463
+ Do not call a setup, draft, provider response, or workflow step a completed GTM outcome unless the requested business result is actually present.