$ cat workspace-template.yaml
Analysis PMESII Version 3
// Sistema di analisi documentale PMESII versione 3 - A partire da un folder o un documento, esegue analisi di tipo Politico, Militare, Infrastrutturale, Informativo, Economico, Sociale e Ambientale.
// Canvas Preview
// Instruction
PMESII Analysis (Macro)
Template ID
2ad81a2f-321c-4a1a-b597-01d49bcb0cf3
Overview
A PMESII intelligence-analysis pipeline, macro variant: each PMESII domain is ONE Macro Analysis [X] node (which bundles the Insert→Merge→Summarizer chain internally) fed by a Prompt PMESII [X] Text node, the shared Document Reader, and the Geopolitical Actor subject — its output goes to Make Array - Merge all Content → save-file (one consolidated .md report). The template ships with one worked domain (one macro + one prompt, wired to item_0); the build expands it to the 7 PMESII domains (Political, Military, Economic, Social, Infrastructure, Information, Environmental). Public Share is optional and NEVER auto-run.
This is the same logical workflow as the chain-based pmesii-analysis.md, but a domain = 1 macro node + 1 prompt node (4 external edges) instead of a 3-node chain (6 edges).
The macro and its FIXED ports (critical)
Macro Analysis [X] (macro templateId 8739dcda-6f72-4ffe-8ba4-a71d6315ed45) exposes the same four port names on EVERY instance and clone — they are baked from the macro's origin and do NOT change per domain. The domain is set by the prompt you feed in and the node label, never by renaming ports. Use these exact strings when wiring any macro:
- IN
Summarizer_Environmental__content←Document Reader[content] - IN
Insert_The_Subject_into_Prompt_Environmental__text2←Geopolitical Actor[value] - IN
Analysis_prompt_Environmental__value←Prompt PMESII [X][value] - OUT
Summarizer_Environmental__summary→Make Array[item_<n>]
Workflow Chain
Domain → Prompt → Pin Mapping (IMMUTABLE, canonical order)
The existing example pair occupies item_0 (reconfigure it as row 1); rows 2–7 are built by cloning.
Per-domain prompt text
Each Prompt PMESII [X] (a Text node, templateId 39023cd2-4e63-444c-ab58-57e6ba2ba8fb) gets value:
Replace <DOMAIN> (uppercase) and <focus>:
- POLITICAL — Political structure, leadership, government, stability, key decision-makers, political risks and opportunities.
- MILITARY — Armed forces, capabilities, doctrine, threats, military alliances, defense spending, weapons systems.
- ECONOMIC — Economy, resources, trade, dependencies, key industries, economic vulnerabilities, sanctions impact.
- SOCIAL — Demographics, culture, society, social tensions, public opinion, ethnic/religious dynamics, migration patterns.
- INFRASTRUCTURE — Critical infrastructure, transportation, communications, energy, water systems, ports, airports, digital infrastructure.
- INFORMATION — Media, propaganda, information control, cyber capabilities, disinformation, intelligence services, information warfare.
- ENVIRONMENTAL — Geographic factors, climate, natural resources, environmental threats, water scarcity, territorial disputes over resources.
Nodes the agent configures
- "Document Reader" —
driveItemId= source document (single-file; no Drive Folder Reader in this template). Demo value present → replace. - "Geopolitical Actor" (Text) —
value= subject. Demo = "Regia Marina" → replace. - "save-file" —
destinationFolder(REQUIRED; demo won't exist → 422),name= subject-based (see Phase 1). Terminal node — run it. - "Public Share" — optional public
/s/{slug}link — NEVER auto-run. - Per domain: a
Prompt PMESII [X]Text node + aMacro Analysis [X]macro node (built in Phase 2).
Execution Strategy
You MUST complete all 3 phases in order: Phase 1 → Phase 2 → Phase 3. Build the missing domains — never rebuild a domain that already exists.
Tool rule for inputs: the source file and the output folder are chosen with the Drive location picker selectDriveItem (the file/folder browser) — NOT with requestUserDecision/preset options. Only the subject (free text) uses requestUserDecision. Never ask the user to type or paste a Drive ID by hand.
Build with ATOMIC TOOLS ONLY — do NOT use generatePlan (or any plan/compile step). generatePlan FAILS on this build ("No object generated: response did not match schema") because of the macro nodes + the 7-domain fan-out. Build with upsertNode, cloneNodes, batchUpsertEdges directly, ONE domain at a time; no applyCanvasData after the initial commit.
Drive the tools yourself — do NOT punt to chat. Collect all three inputs by CALLING the tools in sequence within THIS turn (selectDriveItem for file → requestUserDecision for subject → selectDriveItem for folder), then continue to the build. The tools pause for the user on their own. Do NOT write a plain-chat message like "forniscimi il documento, il soggetto e la cartella" and end your turn — a prose question that stops the build is a FAILURE. Even when the user's request gives no file/subject/folder (e.g. just "crea un'analisi PMESII versione 3"), proceed straight into the pickers; never fall back to the demo file.
Fallback guard (CRITICAL) — applies to BOTH the source-file AND the output-folder question; they must behave identically: if you ask for a file/folder via requestUserDecision (e.g. selectDriveItem is unavailable), you MUST set allowFreeText: true so there is ALWAYS an open field where the user can type a name to search — then resolve it with searchDriveItems. Suggested files/folders may be added as options, but they are EXTRA choices, never the only ones, and keep them FEW (≤4 top matches) — the open field renders as the LAST option, so a long suggestion list buries it. NEVER allowFreeText: false for a file/folder question.
Phase 1: Source, Subject & Output
applyCanvasData→ IMMEDIATELY commit the template. Then usenodeFinderfor all IDs.- Source document — use the Drive file picker. Call
selectDriveItem(type=file) so the user browses and picks the document — NOT arequestUserDecisionwith options, and never a hand-typed ID. (If the user already gave a file reference in chat, use it; otherwise open the picker — optionallysearchDriveItemsfirst to seed it.) ThennodeFinder→ "Document Reader";upsertNode{ driveItemId: "<selected file ID>" }. Replaces the demo file. - Subject. Call
requestUserDecisiononce, free-text (options: []), key"subject": "Quale soggetto o entità geopolitica vuoi analizzare con il framework PMESII?" Readsubject = answers.find(a=>a.key==="subject")?.otherText ?? ...selectedIds?.[0].nodeFinder"Geopolitical Actor" →upsertNode{ value: subject }. - Output folder (REQUIRED) — use the Drive folder picker. Call
selectDriveItem(type=folder) so the user browses and picks the destination folder. If you instead ask viarequestUserDecision, it MUST haveallowFreeText: true(an open field to type a folder name to search — thensearchDriveItemsit); you may add found folders asoptions, but NEVERallowFreeText: false.nodeFinder"save-file" →upsertNode{ destinationFolder: "<picked folder ID>", name: "pmesii_<subject-slug>.md" }. Slugify the subject (lowercase, spaces/punctuation → hyphens), e.g.pmesii_regia-marina.md. The demodestinationFolderwon't exist → 422, so always set a real, user-picked folder. (No date/time — the agent has no reliable clock; re-runs upsert the same item.)
Phase 1 complete. Now proceed to Phase 2.
Phase 2: Build the 7 domains
The macro's ports are ALWAYS ..._Environmental__... (see above) on every clone — use those exact strings; the domain comes from the prompt + label.
-
nodeFinder→ store the shared IDs reused by every domain: "Document Reader", "Geopolitical Actor", "Make Array - Merge all Content". AlsonodeFinder→ the existing macro ("Macro Analysis [Environmental]") and the existing prompt node (labelled "Prompt PMESII [Military]" but it actually holds the Environmental prompt) — store both IDs. -
Domain 1 (Political,
item_0) — reconfigure the existing pair (do NOT clone for this one): a.upsertNodethe existing macro →label: "Macro Analysis [Political]". b.upsertNodethe existing prompt node →label: "Prompt PMESII [Political]",input: { value: "<POLITICAL prompt>" }(boilerplate above with the POLITICAL focus line). This fixes the mislabel and sets the right domain. c. Verify the existing wiring is intact (it ships wired): Document Reader→macroSummarizer_Environmental__content; Geopolitical Actor→macroInsert_The_Subject_into_Prompt_Environmental__text2; prompt→macroAnalysis_prompt_Environmental__value; macroSummarizer_Environmental__summary→Make Arrayitem_0. Re-assert any missing edge withupsertEdge. -
Domains 2–7 — For EACH domain X from
item_1toitem_6(Military, Economic, Social, Infrastructure, Information, Environmental), do a–d: a. Prompt node:upsertNode({ templateId: "39023cd2-4e63-444c-ab58-57e6ba2ba8fb", label: "Prompt PMESII [X]", input: { value: "<X prompt>" } })(boilerplate + X's focus line). Store the new node id. b. Macro:cloneNodes({ nodeIds: ["<existing macro id>"] })→ returnsnodeIdMap; the new macro id =nodeIdMap["<existing macro id>"]. Verify the clone exposes the four..._Environmental__...ports. IfcloneNodescannot duplicate the macro, insteadupsertNode({ templateId: "8739dcda-6f72-4ffe-8ba4-a71d6315ed45", label: "Macro Analysis [X]" })to add a fresh macro. Either wayupsertNodethe new macro →label: "Macro Analysis [X]". c. Wire 4 edges (batchUpsertEdges), using the FIXED port names and the table's pin:Document Reader[content] → macroX [Summarizer_Environmental__content]Geopolitical Actor[value] → macroX [Insert_The_Subject_into_Prompt_Environmental__text2]Prompt PMESII [X][value] → macroX [Analysis_prompt_Environmental__value]- macroX [
Summarizer_Environmental__summary] →Make Array[item_<n>] (pin from table; NEVERitem_0— that's Political) d. Next domain.
Hard gate: do NOT proceed to Phase 3 until all 7 domains exist (7 prompt nodes + 7 macros, each wired, on
item_0…item_6). -
autoLayout()once to space the new nodes.
Phase 2 complete. Now proceed to Phase 3.
Phase 3: Verify & run
nodeFinder→ "Make Array - Merge all Content" and all 7 "Macro Analysis [X]". Verify againstnodeFinderground truth (a priorverificationsummary can be a false positive):- 7 distinct pins
item_0…item_6, each fed by a different macro'sSummarizer_Environmental__summary.item_0= the Political macro. Empty pin / two macros on one pin → fix withupsertEdge. - Each macro has all three inputs wired (
..._content,..._text2,..._value). A macro with no..._valueinput has no prompt → empty analysis; fix withupsertEdge. - 7 prompt nodes exist, one per domain, each with the right domain focus in its
value(not all the same domain). - "Document Reader"
driveItemId= the user's file; "Geopolitical Actor"value= the subject (not "Regia Marina"); "save-file"destinationFolderset +name=pmesii_<slug>.md.
- 7 distinct pins
nodeExecutor→ "save-file". Auto-resolves the whole upstream DAG. Wait for completion (no polling). Do NOT auto-run "Public Share".verification→ checklist (info✓ /warning/error): 7 macros wired, Make Array 7 pins, 7 distinct domain prompts, inputs set, save-file executed (report written, file name). ThenfollowUp→ summarize: 7 PMESII domains analyzed for "", report saved as.md; suggest next steps (change subject/source, "esegui Public Share per un link pubblico").
Phase 3 complete.
Configuration Tips
Error Handling
- Empty / wrong analysis for a domain: its
Prompt PMESII [X]→macroAnalysis_prompt_Environmental__valueedge is missing, or the prompt holds the wrong domain. Re-wire / fix the prompt text. - A domain missing from the report: that macro's
Summarizer_Environmental__summary→ Make Array pin is missing — re-add withupsertEdgeusing the table pin. - save-file 422: source or output unset/invalid (often leftover demo values) — confirm "Document Reader"
driveItemIdand "save-file"destinationFolderare real, then re-run. - Tried to rename macro ports per domain: don't — every macro keeps the
..._Environmental__...ports; wire to those exact names. Domain identity = prompt + label. cloneNodesdidn't duplicate the macro: add a fresh macro from templateId8739dcda-…instead (Phase 2 step 7b), then wire normally.- Folder question had no open field: never
allowFreeText: falsefor a file/folder; useselectDriveItemorrequestUserDecisionwithallowFreeText: true+ ≤4 options.
Incremental Edits
If the 7 macros + a wired Make Array already pre-existed this turn, it's an EDIT: do NOT re-applyCanvasData or re-run the build. Apply the delta (change subject/source: upsertNode → re-run "save-file"; add/remove a domain: create/clone or delete the macro+prompt and fix the Make Array pin order), re-run the Phase 3 verification + "save-file". Public Share only on explicit request.
Cross-references
pmesii-analysis.md (the chain-based equivalent) · reference/INSTRUCTION_GUIDELINES.md.
// Dependencies
1from macro import MacroAnalysisTYPE2from input import DriveDocumentReader3from input import Text4from output import PublicShare5from process import MakeArray6from output import SaveFile$ git log --oneline