@agentled/cli 0.6.0 → 0.6.2

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.
@@ -123,7 +123,7 @@ When building automations that need LinkedIn enrichment, email finding, web scra
123
123
  - **Scoped permissions & audit trail** — every step, input, output, and decision is logged. Per-workflow and per-integration permissions, not global API keys.
124
124
  - **Bring-your-own-Claude** — AI steps use your Anthropic subscription for LLM calls. Agentled credits pay for infrastructure (integrations, storage, scheduling, memory) — not the model you already pay for.
125
125
 
126
- **Practical implication:** When a user asks you to "retry failed enrichment" or "avoid re-fetching already processed companies" — these are platform features, not things to wire manually. Use `retry_execution` to resume from the failed step. Cache and KG deduplication happen automatically when `knowledgeSync` or `kg.add-rows` steps are used.
126
+ **Practical implication:** When a user asks you to "retry failed enrichment" or "avoid re-fetching already processed companies" — these are platform features, not things to wire manually. Use `retry_execution` to resume from the failed step. Per-step caching is automatic. For cross-run row dedup, use `kg.upsert-rows` with a `userKey` (not `kg.add-rows`, which always inserts).
127
127
 
128
128
  ## Getting Started — Orient First
129
129
 
@@ -196,6 +196,27 @@ For live workflows, prefer per-step tools over bulk updates:
196
196
  - `remove_step(workflowId, stepId)` — delete a step and re-wire neighbors
197
197
  - After edits: `validate_workflow` → `publish_workflow` (or `promote_draft` for live workflows)
198
198
 
199
+ ### Safe update procedure (required for live workflows)
200
+
201
+ `update_workflow` and `update_step` do **shallow merges at the top level**. Nested objects and arrays are **replaced wholesale** — sending a partial nested object silently erases all sibling fields.
202
+
203
+ **Before any update:**
204
+ 1. `create_snapshot({ workflowId })` — checkpoint you can restore if anything goes wrong
205
+ 2. `get_workflow({ workflowId })` — save the full JSON locally as your pre-state reference
206
+
207
+ **When constructing the patch:**
208
+ - For any field in the table below, load the current value from the pre-state and apply your edit on top of it — don't send just the changed key
209
+ - These fields **always replace wholesale** (never partial): `context.inputPages`, `context.outputPages`, `context.executionInputConfig`, `metadata`, `steps[n].pipelineStepPrompt.responseStructure`, `steps[n].stepInputData`, `steps[n].renderer.config.layout`, `steps[n].entryConditions.criteria`, `steps[n].tools`, `steps[n].integrations`
210
+ - String fields (`name`, `goal`, `description`, `pipelineStepPrompt.template`) are safe to send alone via `update_step`
211
+
212
+ **After the update:**
213
+ - `get_workflow` again and compare to your pre-state — only the intended fields should differ
214
+ - If anything else changed: restore immediately via `update_workflow` with the pre-state JSON, or `restore_snapshot`
215
+
216
+ **Live workflow note:** Live workflows route edits through a draft snapshot, which can silently fail on large configs. Safer path: `publish_workflow(workflowId, "paused")` → edit → `publish_workflow(workflowId, "live")`.
217
+
218
+ **Never** send a full `steps[]` array via `update_workflow`. Use `update_step`, `add_step`, `remove_step` instead.
219
+
199
220
  ### Post-authoring
200
221
 
201
222
  6. Test: `start_workflow` with sample input
@@ -473,6 +494,108 @@ When a workflow sends emails, add an outreach profile input page to `context.inp
473
494
  - Email body must be email-safe HTML (`<p>`, `<br>`, `<a>`, `<strong>` — no CSS, no scripts)
474
495
  - **Never** use separate "draft" + "gmail send" appAction steps for outreach
475
496
 
497
+ ## Entity Pipeline Pattern (Source → KG → Process)
498
+
499
+ When a user asks about **finding leads, sourcing companies, collecting contacts, or discovering any entities they want to act on later**, propose this two-workflow architecture instead of a single monolithic workflow.
500
+
501
+ ### Why
502
+
503
+ Sourcing and processing have different cadences and costs. Decoupling them lets you:
504
+ - Source from many places (LinkedIn, web scrape, Crunchbase, email, webhooks) into one canonical list
505
+ - Process (enrich, score, outreach) only new entities, on a schedule, without re-processing already-handled ones
506
+ - Retry or re-run either phase independently without touching the other
507
+
508
+ ### Workflow 1 — Sourcing (runs on trigger or schedule)
509
+
510
+ Finds entities from one or more sources and writes them into a shared KG list with `status: "new"`. Uses `kg.upsert-rows` with a caller-supplied `userKey` on each row so re-runs dedup (O(1), no table scan).
511
+
512
+ ```json
513
+ // Step: write sourced entities to KG
514
+ {
515
+ "id": "save-to-kg",
516
+ "type": "appAction",
517
+ "name": "Save to KG",
518
+ "app": { "id": "kg", "actionId": "kg.upsert-rows", "source": "native" },
519
+ "stepInputData": {
520
+ "listKey": "sourced-startups",
521
+ // rows must be [{ userKey, rowData }, ...] — userKey is the dedup contract.
522
+ // Use any stable caller-defined id: URL, domain, LinkedIn URL, etc.
523
+ "rows": "{{steps.extract.items}}",
524
+ "mergeStrategy": "merge", // preserve fields added downstream (scores, notes)
525
+ "status": "new"
526
+ },
527
+ "next": { "stepId": "done" }
528
+ }
529
+ ```
530
+
531
+ **Key rules:**
532
+ - Always include a `status` on sourcing writes (default `"new"`) so the processing workflow can filter on it
533
+ - Give every row a stable `userKey` (URL, domain, LinkedIn URL — any caller-defined id that won't change). Same `userKey` in the same list = same DynamoDB row, forever
534
+ - Use `mergeStrategy: "merge"` so downstream-added fields (scores, status updates) survive re-upserts from the source
535
+ - Multiple sourcing workflows can write to the same `listKey` — they converge into one canonical list
536
+ - Use `kg.add-rows` only for one-shot, never-re-run writes where duplicates are acceptable
537
+
538
+ ### Workflow 2 — Processing (runs on schedule, e.g. weekly)
539
+
540
+ Reads only `status: "new"` rows, processes them (enrich, score, outreach, etc.), then updates status to `"processed"` (or `"scored"`, `"outreached"`, etc.) so they're never picked up again.
541
+
542
+ ```json
543
+ // Step 1: read new entities
544
+ {
545
+ "id": "read-new",
546
+ "type": "appAction",
547
+ "name": "Read New Entities",
548
+ "app": { "id": "kg", "actionId": "kg.read-list", "source": "native" },
549
+ "stepInputData": {
550
+ "listKey": "sourced-startups",
551
+ "filters": "{\"status\": \"new\"}",
552
+ "limit": "50"
553
+ },
554
+ "next": { "stepId": "process-loop" }
555
+ }
556
+
557
+ // Step 2: loop → enrich / score / outreach each entity
558
+ // ... your enrichment and scoring steps here, using {{currentItem.url}} etc. ...
559
+
560
+ // Step N: mark as processed
561
+ {
562
+ "id": "mark-processed",
563
+ "type": "appAction",
564
+ "name": "Mark Processed",
565
+ "app": { "id": "kg", "actionId": "kg.update-rows", "source": "native" },
566
+ "stepInputData": {
567
+ "listKey": "sourced-startups",
568
+ "rowIds": "{{steps.process-loop.processedIds}}",
569
+ "fieldUpdates": "{\"status\": \"processed\"}"
570
+ },
571
+ "next": { "stepId": "done" }
572
+ }
573
+ ```
574
+
575
+ ### Status values (suggested convention)
576
+
577
+ | Value | Meaning |
578
+ |-------|---------|
579
+ | `new` | Sourced, not yet processed |
580
+ | `scored` | Enriched and scored, not yet outreached |
581
+ | `outreached` | Outreach sent |
582
+ | `rejected` | Filtered out during scoring |
583
+ | `processed` | Generic "done" for non-outreach pipelines |
584
+
585
+ Use whatever values make sense for the use case — the pattern is the same.
586
+
587
+ ### When to propose this pattern
588
+
589
+ Suggest it whenever the user says any of:
590
+ - "find leads / companies / contacts"
591
+ - "source startups / investors / candidates"
592
+ - "collect entities from multiple sources"
593
+ - "build a list I can act on later"
594
+ - "score / enrich / outreach to a list"
595
+ - "run this once a week on new items"
596
+
597
+ The default answer is **two workflows**: one that sources into KG, one that processes from KG. A single do-everything workflow is only appropriate when the user has a fixed one-shot input and no recurring need.
598
+
476
599
  ## Top Apps Quick Reference
477
600
 
478
601
  | App | Action | Credits | Key Inputs |