From 3aca153be5d689749c44718af6cd4dc9bf8c4ef1 Mon Sep 17 00:00:00 2001 From: Richard Tang Date: Tue, 17 Mar 2026 16:03:29 -0700 Subject: [PATCH] fix: add missing flowchart and terminal nodes --- examples/templates/sdr_agent/agent.json | 37 ++- examples/templates/sdr_agent/flowchart.json | 270 ++++++++++++++++++++ 2 files changed, 302 insertions(+), 5 deletions(-) create mode 100644 examples/templates/sdr_agent/flowchart.json diff --git a/examples/templates/sdr_agent/agent.json b/examples/templates/sdr_agent/agent.json index 59cb38a6..6752d903 100644 --- a/examples/templates/sdr_agent/agent.json +++ b/examples/templates/sdr_agent/agent.json @@ -14,7 +14,7 @@ "start": "intake" }, "pause_nodes": [], - "terminal_nodes": [], + "terminal_nodes": ["complete"], "conversation_mode": "continuous", "identity_prompt": "You are an SDR (Sales Development Representative) assistant. You help users automate their outreach by scoring contacts, filtering suspicious profiles, generating personalized messages, and creating Gmail drafts — all with human review before anything is sent.", "nodes": [ @@ -193,7 +193,7 @@ "nullable_output_keys": [], "input_schema": {}, "output_schema": {}, - "system_prompt": "You are an SDR assistant. Generate a clear campaign summary report and present it to the user.\n\n**STEP 1 — Load draft records:**\nCall load_data(filename=) to read the draft records.\nIf has_more=true, load additional chunks until all records are loaded.\n\n**STEP 2 — Present the report (text only, NO tool calls):**\n\nPresent a clean summary:\n\nšŸ“Š **SDR Campaign Summary — [outreach_goal]**\n\n**Overview:**\n- Total contacts processed: [N]\n- Contacts filtered (suspicious profiles): [filtered_count]\n- Safe contacts messaged: [N - filtered_count]\n- Gmail drafts created: [N]\n\n**Drafts Created:**\nList each draft: Contact Name | Company | Subject\n\n**Next Steps:**\n\"Your Gmail drafts are ready for review. Please:\n1. Open Gmail and review each draft\n2. Personalize further if needed\n3. Send when ready\n\nWould you like to run another outreach batch or adjust the strategy?\"\n\n**STEP 3 — After the user responds, call set_output:**\n- set_output(\"summary_report\", )", + "system_prompt": "You are an SDR assistant. Generate a clear campaign summary report and present it to the user.\n\n**STEP 1 — Load draft records:**\nCall load_data(filename=) to read the draft records.\nIf has_more=true, load additional chunks until all records are loaded.\n\n**STEP 2 — Present the report (text only, NO tool calls):**\n\nPresent a clean summary:\n\nšŸ“Š **SDR Campaign Summary — [outreach_goal]**\n\n**Overview:**\n- Total contacts processed: [N]\n- Contacts filtered (suspicious profiles): [filtered_count]\n- Safe contacts messaged: [N - filtered_count]\n- Gmail drafts created: [N]\n\n**Drafts Created:**\nList each draft: Contact Name | Company | Subject\n\n**Next Steps:**\n\"Your Gmail drafts are ready for review. Please:\n1. Open Gmail and review each draft\n2. Personalize further if needed\n3. Send when ready\n\nCampaign complete!\"\n\n**STEP 3 — After the user responds, call set_output:**\n- set_output(\"summary_report\", )", "tools": [ "load_data" ], @@ -207,6 +207,33 @@ "max_validation_retries": 2, "client_facing": true, "success_criteria": null + }, + { + "id": "complete", + "name": "Complete", + "description": "Terminal node - campaign complete.", + "node_type": "event_loop", + "input_keys": [ + "summary_report" + ], + "output_keys": [ + "final_report" + ], + "nullable_output_keys": [], + "input_schema": {}, + "output_schema": {}, + "system_prompt": "Campaign is complete. Set the final output.\n\nCall set_output(\"final_report\", )", + "tools": [], + "model": null, + "function": null, + "routes": {}, + "max_retries": 3, + "retry_on": [], + "max_node_visits": 1, + "output_model": null, + "max_validation_retries": 2, + "client_facing": false, + "success_criteria": null } ], "edges": [ @@ -256,9 +283,9 @@ "input_mapping": {} }, { - "id": "report-to-intake", + "id": "report-to-complete", "source": "report", - "target": "intake", + "target": "complete", "condition": "on_success", "condition_expr": null, "priority": 1, @@ -345,7 +372,7 @@ "append_data" ], "metadata": { - "node_count": 6, + "node_count": 7, "edge_count": 6 } } \ No newline at end of file diff --git a/examples/templates/sdr_agent/flowchart.json b/examples/templates/sdr_agent/flowchart.json new file mode 100644 index 00000000..7879dbb0 --- /dev/null +++ b/examples/templates/sdr_agent/flowchart.json @@ -0,0 +1,270 @@ +{ + "original_draft": { + "agent_name": "sdr_agent", + "goal": "Automate sales development outreach: score contacts by priority, filter suspicious profiles, generate personalized messages, and create Gmail drafts for human review.", + "description": "", + "success_criteria": [ + "Contacts are correctly scored and ranked by priority factors (alumni status, connection degree, domain verification)", + "Suspicious profiles (risk_score >= 7) are correctly identified and excluded from outreach", + "Generated messages reference specific profile details (alumni connection, role, company) and match the outreach goal", + "Gmail drafts are created for all safe contacts without errors" + ], + "constraints": [ + "Agent creates Gmail drafts but NEVER sends emails automatically", + "Must not process more contacts than the configured max_contacts parameter", + "Contacts with risk_score >= 7 must be excluded from outreach" + ], + "nodes": [ + { + "id": "intake", + "name": "Intake", + "description": "Receive the contact list and outreach goal from the user. Confirm the strategy and batch size before proceeding.", + "node_type": "event_loop", + "tools": [ + "load_contacts_from_file" + ], + "input_keys": [ + "contacts", + "outreach_goal", + "max_contacts", + "user_background" + ], + "output_keys": [ + "contacts", + "outreach_goal", + "max_contacts", + "user_background" + ], + "success_criteria": "The user has confirmed the contact list, outreach goal, batch size, and their background. All four keys have been written via set_output.", + "sub_agents": [], + "flowchart_type": "start", + "flowchart_shape": "stadium", + "flowchart_color": "#8aad3f" + }, + { + "id": "score-contacts", + "name": "Score Contacts", + "description": "Score and rank each contact from 0 to 100 based on priority factors: alumni status, connection degree, domain verification, mutual connections, and active job postings.", + "node_type": "event_loop", + "tools": [ + "load_data", + "append_data" + ], + "input_keys": [ + "contacts", + "outreach_goal" + ], + "output_keys": [ + "scored_contacts" + ], + "success_criteria": "Every contact has a priority_score field (0-100) and scored_contacts.jsonl has been written and referenced via set_output.", + "sub_agents": [], + "flowchart_type": "database", + "flowchart_shape": "cylinder", + "flowchart_color": "#508878" + }, + { + "id": "filter-contacts", + "name": "Filter Contacts", + "description": "Analyze each contact for authenticity and filter out suspicious profiles. Any contact with a risk score of 7 or higher is skipped.", + "node_type": "event_loop", + "tools": [ + "load_data", + "append_data" + ], + "input_keys": [ + "scored_contacts" + ], + "output_keys": [ + "safe_contacts", + "filtered_count" + ], + "success_criteria": "Each contact has a risk_score and recommendation field. Contacts with risk_score >= 7 are excluded. safe_contacts.jsonl and filtered_count are set via set_output.", + "sub_agents": [], + "flowchart_type": "database", + "flowchart_shape": "cylinder", + "flowchart_color": "#508878" + }, + { + "id": "personalize", + "name": "Personalize", + "description": "Generate a personalized outreach message for each contact based on their profile, shared background, and the user's outreach goal.", + "node_type": "event_loop", + "tools": [ + "load_data", + "append_data" + ], + "input_keys": [ + "safe_contacts", + "outreach_goal", + "user_background" + ], + "output_keys": [ + "personalized_contacts" + ], + "success_criteria": "Every safe contact has an outreach_message field of 80-120 words that references a specific hook from their profile. personalized_contacts.jsonl is set via set_output.", + "sub_agents": [], + "flowchart_type": "database", + "flowchart_shape": "cylinder", + "flowchart_color": "#508878" + }, + { + "id": "send-outreach", + "name": "Send Outreach", + "description": "Create Gmail draft emails for each contact using their personalized message. Drafts are created for human review \u2014 emails are never sent automatically.", + "node_type": "event_loop", + "tools": [ + "gmail_create_draft", + "load_data", + "append_data" + ], + "input_keys": [ + "personalized_contacts", + "outreach_goal" + ], + "output_keys": [ + "drafts_created" + ], + "success_criteria": "A Gmail draft has been created for every safe contact. drafts.jsonl records each draft and drafts_created is set via set_output.", + "sub_agents": [], + "flowchart_type": "database", + "flowchart_shape": "cylinder", + "flowchart_color": "#508878" + }, + { + "id": "report", + "name": "Report", + "description": "Generate a summary report of the outreach campaign: contacts scored, filtered, messaged, and drafts created. Present to user for review.", + "node_type": "event_loop", + "tools": [ + "load_data" + ], + "input_keys": [ + "drafts_created", + "filtered_count", + "outreach_goal" + ], + "output_keys": [ + "summary_report" + ], + "success_criteria": "A campaign summary has been presented to the user listing totals for contacts scored, filtered, messaged, and drafts created. summary_report is set via set_output.", + "sub_agents": [], + "flowchart_type": "terminal", + "flowchart_shape": "stadium", + "flowchart_color": "#b5453a" + } + ], + "edges": [ + { + "id": "edge-0", + "source": "intake", + "target": "score-contacts", + "condition": "on_success", + "description": "", + "label": "" + }, + { + "id": "edge-1", + "source": "score-contacts", + "target": "filter-contacts", + "condition": "on_success", + "description": "", + "label": "" + }, + { + "id": "edge-2", + "source": "filter-contacts", + "target": "personalize", + "condition": "on_success", + "description": "", + "label": "" + }, + { + "id": "edge-3", + "source": "personalize", + "target": "send-outreach", + "condition": "on_success", + "description": "", + "label": "" + }, + { + "id": "edge-4", + "source": "send-outreach", + "target": "report", + "condition": "on_success", + "description": "", + "label": "" + }, + { + "id": "edge-5", + "source": "report", + "target": "intake", + "condition": "on_success", + "description": "", + "label": "" + } + ], + "entry_node": "intake", + "terminal_nodes": [ + "report" + ], + "flowchart_legend": { + "start": { + "shape": "stadium", + "color": "#8aad3f" + }, + "terminal": { + "shape": "stadium", + "color": "#b5453a" + }, + "process": { + "shape": "rectangle", + "color": "#b5a575" + }, + "decision": { + "shape": "diamond", + "color": "#d89d26" + }, + "io": { + "shape": "parallelogram", + "color": "#d06818" + }, + "document": { + "shape": "document", + "color": "#c4b830" + }, + "database": { + "shape": "cylinder", + "color": "#508878" + }, + "subprocess": { + "shape": "subroutine", + "color": "#887a48" + }, + "browser": { + "shape": "hexagon", + "color": "#cc8850" + } + } + }, + "flowchart_map": { + "intake": [ + "intake" + ], + "score-contacts": [ + "score-contacts" + ], + "filter-contacts": [ + "filter-contacts" + ], + "personalize": [ + "personalize" + ], + "send-outreach": [ + "send-outreach" + ], + "report": [ + "report" + ] + } +} \ No newline at end of file