@agentled/cli 0.7.6 → 0.7.7
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.
- package/README.md +18 -1
- package/dist/commands/do.js +1 -1
- package/dist/commands/do.js.map +1 -1
- package/dist/commands/examples.d.ts +5 -5
- package/dist/commands/examples.js +8 -2
- package/dist/commands/examples.js.map +1 -1
- package/dist/commands/onboarding.js +43 -15
- package/dist/commands/onboarding.js.map +1 -1
- package/dist/utils/agentled-home-content.d.ts +1 -1
- package/dist/utils/agentled-home-content.js +6 -3
- package/dist/utils/agentled-home-content.js.map +1 -1
- package/dist/utils/browser-auth.d.ts +1 -0
- package/dist/utils/browser-auth.js +3 -3
- package/dist/utils/browser-auth.js.map +1 -1
- package/dist/utils/pipeline-lint.js +3 -1
- package/dist/utils/pipeline-lint.js.map +1 -1
- package/dist/utils/workspace-meta.d.ts +4 -3
- package/dist/utils/workspace-meta.js +27 -5
- package/dist/utils/workspace-meta.js.map +1 -1
- package/llms-full.txt +4 -2
- package/llms.txt +17 -0
- package/package.json +1 -1
- package/patterns/v1/00-design-principles.md +161 -0
- package/patterns/v1/13-entity-pipeline-lifecycle.md +319 -0
- package/scaffolds/README.md +7 -1
- package/scaffolds/child-with-return.json +71 -0
- package/scaffolds/funnel-orchestrator.json +134 -0
- package/scaffolds/kg-process-update.json +88 -0
- package/scaffolds/orchestrator-kg-loop.json +96 -0
- package/scaffolds/source-from-platform.json +78 -0
- package/scaffolds/source-to-kg.json +88 -0
- package/skills/agentled/SKILL.md +23 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_scaffold": "funnel-orchestrator",
|
|
3
|
+
"_description": "Scheduled KG funnel coordinator: read new rows, call child scoring workflow, read qualified rows, queue outreach workflow, compute KPIs, and finish with a digest.",
|
|
4
|
+
"name": "Scheduled Funnel Orchestrator",
|
|
5
|
+
"goal": "Run a recurring funnel pass across already-working child workflows and report what moved.",
|
|
6
|
+
"description": "Use after sourcing, scoring, contact discovery, and outreach workflows have each passed manual validation.",
|
|
7
|
+
"status": "draft",
|
|
8
|
+
"context": {
|
|
9
|
+
"executionInputConfig": {
|
|
10
|
+
"title": "Run Funnel",
|
|
11
|
+
"description": "Manual override for the scheduled orchestrator.",
|
|
12
|
+
"runCTALabel": "Run funnel",
|
|
13
|
+
"fields": [
|
|
14
|
+
{ "name": "source_list_key", "label": "Source list key", "type": "text", "required": true, "defaultValue": "leads", "description": "Knowledge list key (e.g. \"leads\", \"startups\")." },
|
|
15
|
+
{ "name": "new_status", "label": "New status", "type": "text", "required": true, "defaultValue": "new" },
|
|
16
|
+
{ "name": "qualified_status", "label": "Qualified status", "type": "text", "required": true, "defaultValue": "qualified" },
|
|
17
|
+
{ "name": "score_workflow_id", "label": "Scoring workflow ID", "type": "text", "required": true, "description": "Workflow ID for the child scoring workflow." },
|
|
18
|
+
{ "name": "outreach_workflow_id", "label": "Outreach workflow ID", "type": "text", "required": true, "description": "Workflow ID for the child outreach workflow." }
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"steps": [
|
|
23
|
+
{
|
|
24
|
+
"id": "start",
|
|
25
|
+
"type": "trigger",
|
|
26
|
+
"name": "Scheduled funnel run",
|
|
27
|
+
"pipelineStepStartConditions": {
|
|
28
|
+
"trigger": {
|
|
29
|
+
"type": "schedule",
|
|
30
|
+
"description": "Run weekly.",
|
|
31
|
+
"config": { "frequency": "weekly", "dayOfWeek": "monday", "time": "09:00" }
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"next": { "stepId": "read-new" }
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"id": "read-new",
|
|
38
|
+
"type": "appAction",
|
|
39
|
+
"name": "Read new rows",
|
|
40
|
+
"app": { "id": "kg", "actionId": "kg.read-list", "source": "native" },
|
|
41
|
+
"stepInputData": {
|
|
42
|
+
"listKey": "{{input.source_list_key}}",
|
|
43
|
+
"status": "{{input.new_status || 'new'}}",
|
|
44
|
+
"limit": "25"
|
|
45
|
+
},
|
|
46
|
+
"next": { "stepId": "score-rows" }
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "score-rows",
|
|
50
|
+
"type": "appAction",
|
|
51
|
+
"name": "Run scoring workflow",
|
|
52
|
+
"app": { "id": "agentled", "actionId": "agentled.call-workflow", "source": "native" },
|
|
53
|
+
"stepInputData": {
|
|
54
|
+
"workflowId": "{{input.score_workflow_id}}",
|
|
55
|
+
"executionInputData": "{\"row\": {{newRow}}, \"listKey\": \"{{input.source_list_key}}\"}",
|
|
56
|
+
"timeoutMinutes": "20"
|
|
57
|
+
},
|
|
58
|
+
"loopConfig": {
|
|
59
|
+
"source": "executionContent",
|
|
60
|
+
"config": { "stepId": "read-new", "field": "listEntries" },
|
|
61
|
+
"ItemAlias": "newRow",
|
|
62
|
+
"loopCompletion": { "criteria": "all_items_processed" }
|
|
63
|
+
},
|
|
64
|
+
"creditCost": 0,
|
|
65
|
+
"next": { "stepId": "read-qualified" }
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": "read-qualified",
|
|
69
|
+
"type": "appAction",
|
|
70
|
+
"name": "Read qualified rows",
|
|
71
|
+
"app": { "id": "kg", "actionId": "kg.read-list", "source": "native" },
|
|
72
|
+
"stepInputData": {
|
|
73
|
+
"listKey": "{{input.source_list_key}}",
|
|
74
|
+
"status": "{{input.qualified_status || 'qualified'}}",
|
|
75
|
+
"limit": "25"
|
|
76
|
+
},
|
|
77
|
+
"entryConditions": {
|
|
78
|
+
"onCriteriaFail": "wait",
|
|
79
|
+
"conditionText": "Wait for scoring child workflows to complete.",
|
|
80
|
+
"criteria": [
|
|
81
|
+
{ "type": "loop_completion", "stepId": "score-rows", "operator": "==", "value": true }
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
"next": { "stepId": "queue-outreach" }
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"id": "queue-outreach",
|
|
88
|
+
"type": "appAction",
|
|
89
|
+
"name": "Queue outreach workflow",
|
|
90
|
+
"app": { "id": "agentled", "actionId": "agentled.start-workflow", "source": "native" },
|
|
91
|
+
"stepInputData": {
|
|
92
|
+
"workflowId": "{{input.outreach_workflow_id}}",
|
|
93
|
+
"executionInputData": "{\"row\": {{qualifiedRow}}, \"listKey\": \"{{input.source_list_key}}\"}"
|
|
94
|
+
},
|
|
95
|
+
"entryConditions": {
|
|
96
|
+
"onCriteriaFail": "skip",
|
|
97
|
+
"conditionText": "Skip outreach if no qualified rows are available.",
|
|
98
|
+
"criteria": [
|
|
99
|
+
{ "variable": "{{steps.read-qualified.count}}", "operator": ">", "value": 0 }
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
"loopConfig": {
|
|
103
|
+
"source": "executionContent",
|
|
104
|
+
"config": { "stepId": "read-qualified", "field": "listEntries" },
|
|
105
|
+
"ItemAlias": "qualifiedRow",
|
|
106
|
+
"loopCompletion": { "criteria": "all_items_processed" }
|
|
107
|
+
},
|
|
108
|
+
"creditCost": 0,
|
|
109
|
+
"next": { "stepId": "summarize-run" }
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "summarize-run",
|
|
113
|
+
"type": "aiAction",
|
|
114
|
+
"name": "Summarize run",
|
|
115
|
+
"pipelineStepPrompt": {
|
|
116
|
+
"template": "Create a concise internal funnel digest.\n\nNew rows read: {{steps.read-new.count}}\nQualified rows read: {{steps.read-qualified.count}}\nScoring results: {{steps.score-rows}}\nOutreach starts: {{steps.queue-outreach}}\n\nReturn JSON only.",
|
|
117
|
+
"responseStructure": {
|
|
118
|
+
"summary": "string",
|
|
119
|
+
"newCount": "number",
|
|
120
|
+
"qualifiedCount": "number",
|
|
121
|
+
"outreachQueuedCount": "number",
|
|
122
|
+
"recommendations": ["string"]
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"creditCost": 3,
|
|
126
|
+
"next": { "stepId": "done" }
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"id": "done",
|
|
130
|
+
"type": "milestone",
|
|
131
|
+
"name": "Funnel run complete"
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "KG Process + Update (status state machine)",
|
|
3
|
+
"goal": "Read entities from a KG list filtered by status, process each in a loop, and flip status when done so the same row is never re-processed.",
|
|
4
|
+
"description": "Pattern 15b (processing half of the Source -> Process split) and pattern 12 (KG status as the API between workflows). Pair with `source-to-kg` as the producer. Loop processes one row at a time; after loop completion, `kg.update-rows` flips status to `processed` so the next run only sees what's still `new`.",
|
|
5
|
+
"status": "draft",
|
|
6
|
+
"context": {
|
|
7
|
+
"executionInputConfig": {
|
|
8
|
+
"title": "Process New Entities",
|
|
9
|
+
"description": "Process entities flagged as `new` in the shared KG list.",
|
|
10
|
+
"runCTALabel": "Process",
|
|
11
|
+
"allowRegeneration": false,
|
|
12
|
+
"fields": [
|
|
13
|
+
{ "name": "list_key", "label": "KG list key", "type": "text", "required": true }
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"steps": [
|
|
18
|
+
{
|
|
19
|
+
"id": "schedule",
|
|
20
|
+
"type": "trigger",
|
|
21
|
+
"name": "Daily process",
|
|
22
|
+
"pipelineStepStartConditions": {
|
|
23
|
+
"trigger": {
|
|
24
|
+
"type": "schedule",
|
|
25
|
+
"description": "Run daily at 09:00 — picks up everything sourced overnight.",
|
|
26
|
+
"config": { "frequency": "daily", "time": "09:00" }
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"next": { "stepId": "read-new" }
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "read-new",
|
|
33
|
+
"type": "appAction",
|
|
34
|
+
"name": "Read Rows with status: new",
|
|
35
|
+
"app": { "id": "kg", "actionId": "kg.read-list", "source": "native" },
|
|
36
|
+
"stepInputData": {
|
|
37
|
+
"listKey": "{{input.list_key}}",
|
|
38
|
+
"status": "new",
|
|
39
|
+
"limit": "100"
|
|
40
|
+
},
|
|
41
|
+
"next": { "stepId": "process" }
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "process",
|
|
45
|
+
"type": "aiAction",
|
|
46
|
+
"name": "Process Entity",
|
|
47
|
+
"loopConfig": {
|
|
48
|
+
"source": "executionContent",
|
|
49
|
+
"config": { "stepId": "read-new", "field": "listEntries" },
|
|
50
|
+
"ItemAlias": "row"
|
|
51
|
+
},
|
|
52
|
+
"pipelineStepPrompt": {
|
|
53
|
+
"template": "Process this entity. Replace this prompt with the real processing logic for your domain (enrich, score, classify, draft, etc.).\n\nEntity: {{row}}\n\nReturn the rowId verbatim plus any fields you want merged onto the KG row.",
|
|
54
|
+
"responseStructure": {
|
|
55
|
+
"rowId": "string — copy {{row.id}} verbatim so the update step can target this exact row",
|
|
56
|
+
"result": "object — fields to merge into the KG row (scores, decisions, derived data)"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"creditCost": 5,
|
|
60
|
+
"next": { "stepId": "mark-processed" }
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "mark-processed",
|
|
64
|
+
"type": "appAction",
|
|
65
|
+
"name": "Flip status -> processed",
|
|
66
|
+
"app": { "id": "kg", "actionId": "kg.update-rows", "source": "native" },
|
|
67
|
+
"entryConditions": {
|
|
68
|
+
"onCriteriaFail": "wait",
|
|
69
|
+
"conditionText": "Wait for the processing loop to finish before flipping status.",
|
|
70
|
+
"criteria": [
|
|
71
|
+
{ "type": "loop_completion", "stepId": "process", "operator": "==", "value": true }
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
"stepInputData": {
|
|
75
|
+
"listKey": "{{input.list_key}}",
|
|
76
|
+
"rowIds": "{{steps.process.rowIds}}",
|
|
77
|
+
"fieldUpdates": "{{steps.process.results}}",
|
|
78
|
+
"status": "processed"
|
|
79
|
+
},
|
|
80
|
+
"next": { "stepId": "done" }
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "done",
|
|
84
|
+
"type": "milestone",
|
|
85
|
+
"name": "Processing Done"
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Orchestrator: Loop call-workflow over KG",
|
|
3
|
+
"goal": "Read rows from a KG list, call a child workflow per row to score/process each, persist the results back to KG, then summarize.",
|
|
4
|
+
"description": "Pattern 11 (orchestrator) wired to a child built from the `child-with-return` scaffold. The KG list is the source of truth; the child encapsulates the per-row logic. Uses `entryConditions.type: \"loop_completion\"` with `onCriteriaFail: \"wait\"` so downstream steps block until every child finishes.",
|
|
5
|
+
"status": "draft",
|
|
6
|
+
"context": {
|
|
7
|
+
"executionInputConfig": {
|
|
8
|
+
"title": "Orchestrate Scoring",
|
|
9
|
+
"description": "Score every `new` row in the KG list by calling a child workflow per row.",
|
|
10
|
+
"runCTALabel": "Run",
|
|
11
|
+
"allowRegeneration": false,
|
|
12
|
+
"fields": [
|
|
13
|
+
{ "name": "source_list_key", "label": "Source KG list key", "type": "text", "required": true },
|
|
14
|
+
{ "name": "child_workflow_id", "label": "Child workflow id (the scoring workflow)", "type": "text", "required": true }
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"steps": [
|
|
19
|
+
{
|
|
20
|
+
"id": "start",
|
|
21
|
+
"type": "trigger",
|
|
22
|
+
"name": "Manual Start",
|
|
23
|
+
"pipelineStepStartConditions": { "trigger": { "type": "manual" } },
|
|
24
|
+
"next": { "stepId": "read-candidates" }
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "read-candidates",
|
|
28
|
+
"type": "appAction",
|
|
29
|
+
"name": "Read Candidates from KG",
|
|
30
|
+
"app": { "id": "kg", "actionId": "kg.read-list", "source": "native" },
|
|
31
|
+
"stepInputData": {
|
|
32
|
+
"listKey": "{{input.source_list_key}}",
|
|
33
|
+
"status": "new",
|
|
34
|
+
"limit": "50"
|
|
35
|
+
},
|
|
36
|
+
"next": { "stepId": "call-child" }
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "call-child",
|
|
40
|
+
"type": "appAction",
|
|
41
|
+
"name": "Score Row (child workflow)",
|
|
42
|
+
"loopConfig": {
|
|
43
|
+
"source": "executionContent",
|
|
44
|
+
"config": { "stepId": "read-candidates", "field": "listEntries" },
|
|
45
|
+
"ItemAlias": "row"
|
|
46
|
+
},
|
|
47
|
+
"app": { "id": "agentled", "actionId": "agentled.call-workflow", "source": "native" },
|
|
48
|
+
"stepInputData": {
|
|
49
|
+
"workflowId": "{{input.child_workflow_id}}",
|
|
50
|
+
"executionInputData": "{\"entity_id\": \"{{row.id}}\", \"entity_url\": \"{{row.url}}\"}",
|
|
51
|
+
"timeoutMinutes": "30"
|
|
52
|
+
},
|
|
53
|
+
"next": { "stepId": "persist-scores" }
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"id": "persist-scores",
|
|
57
|
+
"type": "appAction",
|
|
58
|
+
"name": "Write Scores Back to KG",
|
|
59
|
+
"app": { "id": "kg", "actionId": "kg.update-rows", "source": "native" },
|
|
60
|
+
"entryConditions": {
|
|
61
|
+
"onCriteriaFail": "wait",
|
|
62
|
+
"conditionText": "Wait for every child call to complete before flipping status.",
|
|
63
|
+
"criteria": [
|
|
64
|
+
{ "type": "loop_completion", "stepId": "call-child", "operator": "==", "value": true }
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
"stepInputData": {
|
|
68
|
+
"listKey": "{{input.source_list_key}}",
|
|
69
|
+
"rowIds": "{{steps.call-child.rowIds}}",
|
|
70
|
+
"fieldUpdates": "{{steps.call-child.returnData}}",
|
|
71
|
+
"status": "scored"
|
|
72
|
+
},
|
|
73
|
+
"next": { "stepId": "summarize" }
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"id": "summarize",
|
|
77
|
+
"type": "aiAction",
|
|
78
|
+
"name": "Summarize Run",
|
|
79
|
+
"pipelineStepPrompt": {
|
|
80
|
+
"template": "Summarize this orchestration run.\n\nRows processed: {{steps.read-candidates.count}}\nResults: {{steps.call-child.returnData}}\n\nReport totals, top-3 by score, and anything that looked anomalous.",
|
|
81
|
+
"responseStructure": {
|
|
82
|
+
"totals": "object — counts by decision bucket",
|
|
83
|
+
"top": "array — top 3 rows",
|
|
84
|
+
"notes": "string"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"creditCost": 5,
|
|
88
|
+
"next": { "stepId": "done" }
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"id": "done",
|
|
92
|
+
"type": "milestone",
|
|
93
|
+
"name": "Orchestration Done"
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_scaffold": "source-from-platform",
|
|
3
|
+
"_description": "Source entities from a native app, normalize them, and upsert to KG with status:new. Pair with a downstream scoring workflow that reads status:new.",
|
|
4
|
+
"name": "Source from Platform",
|
|
5
|
+
"goal": "Source entities from a platform and write them to a Knowledge Graph list for downstream processing.",
|
|
6
|
+
"status": "draft",
|
|
7
|
+
"context": {
|
|
8
|
+
"executionInputConfig": {
|
|
9
|
+
"title": "Run Sourcing",
|
|
10
|
+
"description": "Source entities and add them to the Knowledge Graph.",
|
|
11
|
+
"runCTALabel": "Source",
|
|
12
|
+
"fields": [
|
|
13
|
+
{ "name": "search_query", "label": "Search query", "type": "text", "required": true },
|
|
14
|
+
{ "name": "target_list_key", "label": "Target list key", "type": "text", "required": true, "defaultValue": "leads", "description": "Knowledge list key (e.g. \"leads\", \"startups\")." }
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"steps": [
|
|
19
|
+
{
|
|
20
|
+
"id": "start",
|
|
21
|
+
"type": "trigger",
|
|
22
|
+
"name": "Scheduled sourcing",
|
|
23
|
+
"pipelineStepStartConditions": {
|
|
24
|
+
"trigger": {
|
|
25
|
+
"type": "schedule",
|
|
26
|
+
"description": "Run weekly.",
|
|
27
|
+
"config": { "frequency": "weekly", "dayOfWeek": "monday", "time": "08:00" }
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"next": { "stepId": "source-entities" }
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "source-entities",
|
|
34
|
+
"type": "appAction",
|
|
35
|
+
"name": "Source entities",
|
|
36
|
+
"_comment": "Replace the app with the source action. Run: agentled apps for-source <platform>",
|
|
37
|
+
"app": { "id": "REPLACE_WITH_APP_ID", "actionId": "REPLACE_WITH_APP_ID.REPLACE_WITH_ACTION_ID", "source": "native" },
|
|
38
|
+
"stepInputData": {
|
|
39
|
+
"query": "{{input.search_query}}",
|
|
40
|
+
"limit": "25"
|
|
41
|
+
},
|
|
42
|
+
"creditCost": 2,
|
|
43
|
+
"next": { "stepId": "normalize-entities" }
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "normalize-entities",
|
|
47
|
+
"type": "aiAction",
|
|
48
|
+
"name": "Normalize entities",
|
|
49
|
+
"pipelineStepPrompt": {
|
|
50
|
+
"template": "Extract real entities from the source output.\n\nSource output:\n{{steps.source-entities}}\n\nRules:\n- Keep only identifiable entities.\n- Use a stable userKey, preferably domain, profile URL, email, or canonical source URL.\n- Set rowData.status to \"new\".\n- Include source, source_url, sourced_at, and enough evidence for a downstream scoring workflow.\n- Do not score, find contacts, or draft outreach here.\n\nReturn JSON only.",
|
|
51
|
+
"responseStructure": {
|
|
52
|
+
"rows": "array of { userKey: string, rowData: object }",
|
|
53
|
+
"count": "number"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"creditCost": 5,
|
|
57
|
+
"next": { "stepId": "save-entities" }
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": "save-entities",
|
|
61
|
+
"type": "appAction",
|
|
62
|
+
"name": "Save entities",
|
|
63
|
+
"app": { "id": "kg", "actionId": "kg.upsert-rows", "source": "native" },
|
|
64
|
+
"stepInputData": {
|
|
65
|
+
"listKey": "{{input.target_list_key}}",
|
|
66
|
+
"rows": "{{steps.normalize-entities.rows}}",
|
|
67
|
+
"mergeStrategy": "merge",
|
|
68
|
+
"status": "new"
|
|
69
|
+
},
|
|
70
|
+
"next": { "stepId": "done" }
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": "done",
|
|
74
|
+
"type": "milestone",
|
|
75
|
+
"name": "Sourcing complete"
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Source -> KG (idempotent sourcing)",
|
|
3
|
+
"goal": "Find entities and write them to a KG list with a stable userKey so re-running never produces duplicates.",
|
|
4
|
+
"description": "Pattern 15a (sourcing half of the Source -> Process split). Pair this scaffold with `kg-process-update` as the consumer. Uses `kg.upsert-rows` with `userKey` for O(1) dedup across runs and `status: \"new\"` so the processing workflow can filter cleanly.",
|
|
5
|
+
"status": "draft",
|
|
6
|
+
"context": {
|
|
7
|
+
"executionInputConfig": {
|
|
8
|
+
"title": "Source Entities",
|
|
9
|
+
"description": "Find entities and add them to the shared KG list.",
|
|
10
|
+
"runCTALabel": "Source",
|
|
11
|
+
"allowRegeneration": false,
|
|
12
|
+
"fields": [
|
|
13
|
+
{ "name": "search_query", "label": "Search query / topic", "type": "text", "required": true },
|
|
14
|
+
{ "name": "target_list_key", "label": "Target KG list key", "type": "text", "required": true }
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"steps": [
|
|
19
|
+
{
|
|
20
|
+
"id": "schedule",
|
|
21
|
+
"type": "trigger",
|
|
22
|
+
"name": "Weekly source",
|
|
23
|
+
"pipelineStepStartConditions": {
|
|
24
|
+
"trigger": {
|
|
25
|
+
"type": "schedule",
|
|
26
|
+
"description": "Run weekly on Monday morning.",
|
|
27
|
+
"config": { "frequency": "weekly", "dayOfWeek": "monday", "time": "08:00" }
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"next": { "stepId": "generate-queries" }
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "generate-queries",
|
|
34
|
+
"type": "aiAction",
|
|
35
|
+
"name": "Generate Optimized Queries",
|
|
36
|
+
"pipelineStepPrompt": {
|
|
37
|
+
"template": "Generate 3 optimized search queries to find new entities matching: {{input.search_query}}\n\nUse boolean operators and filters appropriate to the target platform. Return a flat list of strings.",
|
|
38
|
+
"responseStructure": {
|
|
39
|
+
"queries": "array of strings"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"creditCost": 3,
|
|
43
|
+
"next": { "stepId": "search" }
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "search",
|
|
47
|
+
"type": "appAction",
|
|
48
|
+
"name": "Search (replace with target platform)",
|
|
49
|
+
"app": { "id": "REPLACE_WITH_APP_ID", "actionId": "REPLACE_WITH_APP_ID.REPLACE_WITH_ACTION_ID", "source": "native" },
|
|
50
|
+
"stepInputData": {
|
|
51
|
+
"queries": "{{steps.generate-queries.queries}}"
|
|
52
|
+
},
|
|
53
|
+
"creditCost": 2,
|
|
54
|
+
"next": { "stepId": "extract" }
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "extract",
|
|
58
|
+
"type": "aiAction",
|
|
59
|
+
"name": "Extract Entities",
|
|
60
|
+
"pipelineStepPrompt": {
|
|
61
|
+
"template": "Extract structured entity records from this raw source output.\n\nSource: {{steps.search.output}}\n\nEvery row MUST include a stable identifier (canonical URL, domain, or platform id) — this becomes the userKey for KG dedup. Drop rows you cannot uniquely identify.",
|
|
62
|
+
"responseStructure": {
|
|
63
|
+
"items": "array of { userKey: string (stable id e.g. canonical URL), rowData: { name, url, description, ...other fields } }"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"creditCost": 5,
|
|
67
|
+
"next": { "stepId": "save-to-kg" }
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "save-to-kg",
|
|
71
|
+
"type": "appAction",
|
|
72
|
+
"name": "Upsert to KG (status: new)",
|
|
73
|
+
"app": { "id": "kg", "actionId": "kg.upsert-rows", "source": "native" },
|
|
74
|
+
"stepInputData": {
|
|
75
|
+
"listKey": "{{input.target_list_key}}",
|
|
76
|
+
"rows": "{{steps.extract.items}}",
|
|
77
|
+
"mergeStrategy": "merge",
|
|
78
|
+
"status": "new"
|
|
79
|
+
},
|
|
80
|
+
"next": { "stepId": "done" }
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "done",
|
|
84
|
+
"type": "milestone",
|
|
85
|
+
"name": "Sourcing Done"
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
}
|
package/skills/agentled/SKILL.md
CHANGED
|
@@ -42,6 +42,28 @@ After orientation, ask **at most three to five** targeted questions. Focus only
|
|
|
42
42
|
- Every possible future integration question before the first useful slice is designed.
|
|
43
43
|
- Anything answerable by running `agentled workspace inspect`.
|
|
44
44
|
|
|
45
|
+
## Outreach scale and segmentation
|
|
46
|
+
|
|
47
|
+
For outbound, sales, investor, founder, or lead-generation workflows, classify the motion before designing the workflow. See `docs/OUTREACH_SCALE_GUIDANCE.md`.
|
|
48
|
+
|
|
49
|
+
**Core diagnostic:**
|
|
50
|
+
- PCPL = prospects contacted / positive replies over the last 30 days. PCPL at or below 250 is a scalable winner; above 250 means diagnose deliverability, then copy, then offer-audience match.
|
|
51
|
+
- Daily volume = last 30 days sent / 22 working days.
|
|
52
|
+
- TAM = total reachable prospects in the CRM, KG list, enrichment tool, or target account universe.
|
|
53
|
+
- Reply ops = whether positive replies are handled quickly and followed up persistently.
|
|
54
|
+
|
|
55
|
+
**Tier guidance:**
|
|
56
|
+
- Tier 1 (~100/day, a few thousand prospects): enrich every account, route by strongest signal, use high-touch multi-channel outreach. This is the default for most small Agentled Ops / AngelHive-style motions.
|
|
57
|
+
- Tier 2 (~1,000/day, 50K-100K prospects): split into top 200-500 home-run accounts with Tier 1 treatment plus segmented automation for the long tail.
|
|
58
|
+
- Tier 3 (~10K/day, hundreds of thousands): test angle x offer x segment, generate script variations, keep tests running in parallel, and track PCPL per combination.
|
|
59
|
+
- Tier 4 (50K-100K/day, millions): require provider segmentation, live monitoring, sender reserve capacity, hourly testing cadence, and reply-handling SLAs before increasing volume.
|
|
60
|
+
|
|
61
|
+
**Workflow implications:**
|
|
62
|
+
- Small TAM problems are usually segmentation and signal-enrichment problems, not copy-only problems.
|
|
63
|
+
- Store `outreachAngle`, `offer`, `segment`, `campaignVariant`, `channelUsed`, `sender`, `contactedAt`, `replyStatus`, `meetingStatus`, and `positiveReplyAt` when the KG schema allows it.
|
|
64
|
+
- Configure business metrics for prospects contacted, positive replies, PCPL, meetings/bookings/paid confirmations, bounce/failed-send count, and segment/angle performance. These are `analyticsConfig` business metrics, not ROI assumptions.
|
|
65
|
+
- Literal PCPL should use `type: "ratio"` with `ratioMode: "raw"`. Use the default percentage ratio behavior for rates such as `positive_replies / prospects_contacted`.
|
|
66
|
+
|
|
45
67
|
## Valid step types (closed list)
|
|
46
68
|
|
|
47
69
|
Every pipeline step **must** set `type` to one of these values. Any other value is silently normalised/rejected and the step won't execute. For full input/output schemas call `get_step_schema`.
|
|
@@ -111,6 +133,7 @@ agentled best-practices # summary + link to agentic-
|
|
|
111
133
|
| **Outreach** — personalized email with user approval | `08-composed-email-approval` (outreachProfile + `pipelineStepPrompt.type: "email"` + `schedule-email`) | `list-match-email` |
|
|
112
134
|
| **Report / dashboard** — structured output + sharing + KPI history | `09-reports-and-knowledge-storage` (Config renderer + share step + `knowledgeSync`) | `lead-scoring-kg`, `extract-threshold-alert` |
|
|
113
135
|
| **Multi-workflow system** — workflows sharing KG state and status transitions | `12-event-driven-workflow-groups` (group manifest, state machines, build order) | — |
|
|
136
|
+
| **Entity pipeline group** — sourcing → score/qualify → find contact → outreach → scheduled orchestrator | `13-entity-pipeline-lifecycle` | `source-from-platform`, `lead-scoring-kg`, `list-match-email`, `funnel-orchestrator` |
|
|
114
137
|
|
|
115
138
|
Full patterns are maintained publicly at https://github.com/agentled/agentic-ops — the CLI ships a mirrored copy, see `agentled examples`. Scaffolds are preflight-clean pipeline JSON skeletons; start from one instead of writing from scratch.
|
|
116
139
|
|