Skip to content

Instantly share code, notes, and snippets.

@iggyughgi-glitch
Created April 16, 2026 08:40
Show Gist options
  • Select an option

  • Save iggyughgi-glitch/7cf601cf7932eb7097899ce96625cbbd to your computer and use it in GitHub Desktop.

Select an option

Save iggyughgi-glitch/7cf601cf7932eb7097899ce96625cbbd to your computer and use it in GitHub Desktop.
Nnn
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Agent-Flow n8n Edition</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Space+Mono&family=Syne:wght@800&display=swap');
body { margin: 0; background: #0d0f14; color: #e2e8f0; font-family: 'Space Mono', monospace; font-size: 14px; }
.canvas { padding: 20px; display: flex; flex-direction: column; align-items: center; gap: 20px; }
.node {
background: #181c27; border: 1px solid #252a3a; border-radius: 12px;
padding: 16px; width: 100%; max-width: 400px; position: relative;
transition: all 0.3s ease; box-shadow: 0 4px 20px rgba(0,0,0,0.5);
}
.node-running { border-color: #a78bfa; box-shadow: 0 0 15px rgba(167, 139, 250, 0.3); }
.node-done { border-color: #22d3a0; }
.connector { width: 2px; height: 20px; background: #252a3a; margin: -20px 0; z-index: -1; }
.btn-glow:active { transform: scale(0.98); }
input, textarea, button { background: #13161e; border: 1px solid #252a3a; color: #fff; padding: 12px; border-radius: 8px; margin-bottom: 10px; font-family: inherit; }
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { useState, useEffect } = React;
function App() {
const [task, setTask] = useState("");
const [apiKey, setApiKey] = useState(localStorage.getItem("ant_key") || "");
const [nodes, setNodes] = useState([]);
const [status, setStatus] = useState("idle");
const callClaude = async (messages, system) => {
const url = `https://corsproxy.io/?${encodeURIComponent("https://api.anthropic.com/v1/messages")}`;
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json", "x-api-key": apiKey, "anthropic-version": "2023-06-01" },
body: JSON.stringify({ model: "claude-3-haiku-20240307", max_tokens: 1024, system, messages })
});
const data = await res.json();
if (data.error) throw new Error(data.error.message);
return data.content[0].text;
};
const runWorkflow = async () => {
if (!apiKey || !task) return alert("Missing Key/Task");
setStatus("running");
setNodes([{ id: 't1', type: 'TRIGGER', title: task, status: 'done' }]);
try {
// Planning Step
const pNode = { id: 'p1', type: 'PLANNER', title: "Breaking down task...", status: 'running' };
setNodes(prev => [...prev, pNode]);
const planRes = await callClaude([{ role: "user", content: task }], "Respond ONLY with a JSON object: { \"steps\": [ { \"title\": \"...\", \"desc\": \"...\" } ] }");
const plan = JSON.parse(planRes.replace(/```json|```/g, "")).steps;
setNodes(prev => prev.map(n => n.id === 'p1' ? {...n, status: 'done', output: plan.map(s => s.title).join('\n')} : n));
// Execution Steps
for (let i = 0; i < plan.length; i++) {
const step = plan[i];
const eNode = { id: `e${i}`, type: 'EXECUTE', title: step.title, status: 'running' };
setNodes(prev => [...prev, eNode]);
const output = await callClaude([{ role: "user", content: `Step: ${step.title}. Task: ${step.desc}` }], "Execute step briefly.");
setNodes(prev => prev.map(n => n.id === eNode.id ? {...n, status: 'done', output} : n));
}
setNodes(prev => [...prev, { id: 'done', type: 'RESULT', title: "Workflow Complete", status: 'done' }]);
} catch (e) {
setNodes(prev => [...prev, { id: 'err', type: 'ERROR', title: "Error", output: e.message }]);
} finally { setStatus("idle"); }
};
return (
<div className="canvas">
<div style={{ width: '100%', maxWidth: 400 }}>
<h2 style={{ color: '#3d7fff', fontFamily: 'Syne', textAlign: 'center' }}>AGENT·FLOW</h2>
<input type="password" value={apiKey} placeholder="Paste sk-ant-..." onChange={e => {setApiKey(e.target.value); localStorage.setItem("ant_key", e.target.value)}} />
<textarea value={task} placeholder="Enter workflow task..." onChange={e => setTask(e.target.value)} />
<button onClick={runWorkflow} disabled={status === 'running'} style={{ background: '#3d7fff', fontWeight: 'bold' }}>
{status === 'running' ? "EXECUTING..." : "DEPLOY WORKFLOW"}
</button>
</div>
{nodes.map((n, i) => (
<React.Fragment key={n.id}>
{i > 0 && <div className="connector" />}
<div className={`node ${n.status === 'running' ? 'node-running' : n.status === 'done' ? 'node-done' : ''}`}>
<div style={{ fontSize: '9px', color: '#64748b', fontWeight: 'bold' }}>{n.type}</div>
<div style={{ fontWeight: 'bold', margin: '4px 0' }}>{n.title}</div>
{n.output && <div style={{ fontSize: '11px', color: '#94a3b8', borderTop: '1px solid #252a3a', paddingTop: '8px', marginTop: '8px', whiteSpace: 'pre-wrap' }}>{n.output}</div>}
</div>
</React.Fragment>
))}
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment