Everyone types prompts. Few testers know when a prompt should graduate into a skill file, and when a skill should graduate into a full AI agent. One table, two hand-drawn diagrams, and the same QA job, a test plan from a Jira ticket, done all four ways.
The fastest way to see the difference: hold the job still and change the packaging. The job here is always the same, "turn Jira story QAJB-42 into a QA test plan". What changes is where the instructions live, who triggers them, and how much of the work the system does without you.
| Normal prompt | Vibe-coded prompt | Skill file | AI agent | |
|---|---|---|---|---|
| What it is | One instruction typed into chat | A chat conversation you steer by feel, "make it pop" | A folder with SKILL.md instructions + optional scripts | A system: model + tools + a loop that finishes the job |
| Where it lives | Your head and the chat history | The chat scroll, gone tomorrow | Versioned in git, ~/.claude/skills/ | A deployed flow (Langflow, CrewAI, Claude Code) |
| Who triggers it | You, manually, every time | You, again and again | The agent, when your request matches its description | A trigger: chat message, webhook, schedule |
| Repeatable? | Only if you retype it exactly | No. Nobody can reproduce it, including you | Yes. Same rubric, same steps, every run | Yes. Runs on demand, same flow every time |
| Can run code / tools? | No | No | Yes, bundled scripts (fetch Jira, export PDF) | Yes, that is the point: fetch, decide, act, export |
| Team sharing | Copy-paste into Slack | A screenshot, at best | git clone, or a .zip anyone drops in | Deploy once, whole team uses it |
| Quality control | Varies run to run | Pure vibes, review skipped | Rubric + review gate pinned in the file | Pinned by the flow, plus the skills it loads |
| Best for | A quick one-off | Throwaway exploration | A repeatable expert workflow | An end-to-end job with fetching + files |
| The example | "Write test cases for login" | "make the plan nicer... ok ship it" | test-plan-from-jira | Langflow: fetch QAJB-42, plan, export PDF |
You type an instruction, the model answers, done. Perfect for a one-off. The problem shows up on Tuesday, when a teammate needs the same output and types a worse version of your prompt from memory.
Write a QA test plan for this story: "As a shopper I can apply a coupon code at checkout". Include positive, negative and edge cases in a table with steps and expected results.
Good output, zero leverage: the instruction dies with the chat tab. Nothing is versioned, nothing is triggered automatically, no script ran.
"Vibe coding" is prompting by feel: you glance at the output, nudge it, glance again, and accept whatever looks right without reading the details. It is genuinely great for exploring what is possible, and genuinely dangerous the moment the output matters.
you: make me a test plan for the coupon story, make it look nice ai: (writes a plan) you: more edge cases. and severity colors. make the table bigger ai: (rewrites it) you: the boundary ones feel wrong, redo just those, keep the vibe ai: (rewrites again) you: looks good, ship it
A skill (per the agentskills.io format) is a folder with a SKILL.md: a short front-matter (name + description) and a body of instructions, plus any scripts it needs. The description is the trigger: when your request matches it, the agent loads the file and follows it, running the bundled scripts as needed. Here is the real one from our library, condensed:
--- name: test-plan-from-jira description: Fetch a Jira story by key and generate a complete QA test plan (scope, scenarios, positive / negative / edge cases), then export it to a polished PDF and a filable XLSX. Use whenever the user says "create a test plan from <JIRA-KEY>" or asks to export a test plan to PDF / Excel. --- # Test Plan from Jira 1. Get the Jira key from the user (e.g. QAJB-42). 2. Fetch the story: python scripts/fetch_jira.py QAJB-42 > story.json 3. Design the plan: every acceptance criterion maps to at least one positive AND one negative case. Keep steps atomic and verifiable. 4. Export: python scripts/export.py plan.json -> PDF + XLSX. 5. Summarize scope + case counts back to the user.
Now the Tuesday problem is solved: the teammate types "create a test plan from QAJB-43", the agent matches the description, and the exact same workflow runs, rubric included. The prompt became infrastructure.
An agent is not a bigger prompt. It is a system: a model wired to tools inside a loop, so it can fetch its own inputs, decide, act, and hand you finished files. In Langflow you drag this together as nodes; the same shape works in CrewAI or Claude Code. For our job the flow is four nodes:
Notice what happened: the skill did not get replaced, it got embedded. The agent supplies the loop and the tools; the SKILL.md supplies the judgment (every AC gets a negative case, steps stay atomic). This is why the ladder matters: good agents are built out of good skills, which are promoted from prompts that worked.
| What you do | What you get | Next week | |
|---|---|---|---|
| Prompt | Type the whole instruction, paste the story in | One decent plan in the chat | Retype it, slightly worse |
| Vibe-coded | Nudge the output five times by feel | A plan that "looks good" | Cannot be reproduced, even by you |
| Skill | Say "create a test plan from QAJB-42" | The same rubric-driven plan, every time, + PDF/XLSX via scripts | Teammate runs it unchanged from git |
| Agent | Send the key to the flow (chat, webhook, or schedule) | Fetched story, generated plan, exported files, no human steps between | Runs itself; you review the output |
n8n (pronounced "n-eight-n") is the drag-and-drop workflow tool the agent examples on the first tab talk about. This tab gets it running on Windows and Mac, via Node or Docker, then builds the simplest useful agent: a test plan generator from a Jira ticket.
Two good paths. Node is quickest to try; Docker is cleaner to keep. Either way you end at http://localhost:5678.
Windows Install Node.js 20 LTS from nodejs.org (or winget install OpenJS.NodeJS.LTS), then in PowerShell:
node -v # confirm v20+ npm install n8n -g n8n # starts the editor at http://localhost:5678
Mac With Homebrew:
brew install node@20
npm install n8n -g
n8n # same: http://localhost:5678
No global install wanted? npx n8n runs it one-off. Update later with npm update -g n8n.
Install Docker Desktop first (Windows needs WSL2 enabled; the installer handles it). Then the same two commands work on both systems:
docker volume create n8n_data docker run -it --rm --name n8n -p 5678:5678 \ -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n
The volume keeps your workflows across restarts. To run it in the background swap -it --rm for -d --restart unless-stopped. Update with docker pull docker.n8n.io/n8nio/n8n.
Four nodes. This is the exact flow shape from the first tab's "AI agent" section, made real:
{{ $json.chatInput }}.QAJB-42, get a full test plan back. Activate the workflow to keep it always on.You are a senior QA engineer. You will receive a Jira story (summary, description, acceptance criteria). Produce a complete test plan: - Scope and assumptions (what is and is not tested) - Test scenarios grouped by feature area - For each case: id, title, type (positive/negative/edge/boundary), priority P1-P3, preconditions, numbered steps, expected result - Every acceptance criterion gets at least one positive AND one negative case. Steps atomic, expected results verifiable. - If the story is thin, list your assumptions at the top. Return the plan as clean markdown with one table per feature area.
From here the upgrades are one node each: send the plan to Confluence or email, trigger from a Jira webhook when a story hits READY instead of chat, or export XLSX with the spreadsheet node. The skill version of this generator is the portable twin of this flow.
LangFlow is the visual builder for LangChain-style agents: components on a canvas, wires between them, a Playground to chat with the result. This tab installs it on Windows and Mac, via pip/uv or Docker, then rebuilds the same Jira test plan generator so you can compare it with the n8n version side by side.
You need Python 3.10 or newer. The uv installer is the fast, clean way:
python --version # 3.10+ (Windows: from python.org, Mac: brew install python) pip install uv # fast installer, once uv pip install langflow # or plain: pip install langflow uv run langflow run # or plain: langflow run
It prints a local URL, open http://127.0.0.1:7860. On Mac there is also a one-click LangFlow Desktop app if you want zero terminal.
With Docker Desktop installed (same note as the n8n tab: Windows wants WSL2), one command:
docker run -it --rm -p 7860:7860 langflowai/langflow:latest
Open http://localhost:7860. To keep flows across restarts, mount a volume:
docker volume create langflow_data docker run -d --restart unless-stopped -p 7860:7860 \ -v langflow_data:/app/langflow langflowai/langflow:latest
Five components, wired left to right. Start from a blank flow (or the "Basic Prompting" template and add the API Request):
https://YOURSITE.atlassian.net/rest/api/3/issue/<KEY>. Add a header Authorization: Basic <base64 of email:api_token> (make the token at id.atlassian.com). Wire Chat Input into the URL's key so the typed key is fetched.{ticket} (wire the API Request output here) and the instructions baked in.QAJB-42, read your test plan. Every LangFlow flow also exposes an API endpoint, so this generator is callable from CI later.You are a senior QA engineer. Below is a Jira story fetched as JSON.
{ticket}
Produce a complete test plan from it:
- Scope and assumptions (what is and is not tested)
- Test scenarios grouped by feature area
- For each case: id, title, type (positive/negative/edge/boundary),
priority P1-P3, preconditions, numbered steps, expected result
- Every acceptance criterion gets at least one positive AND one
negative case. Steps atomic, expected results verifiable.
Return clean markdown with one table per feature area.
Same job, three shapes now: the skill (portable, lives in git), the n8n flow (always-on automation), and this LangFlow flow (visual, API-exposed). That is the ladder from the first tab, walked end to end.
The first tab warned that vibe coding is unrepeatable. Here is the honest fix: keep the vibe loop, but start it from a written spec prompt. Below is a complete one. Paste it into DeepSeek, Gemini Flash, Groq's gpt-oss-120b, or Claude, and you get a working local Jira Chat app: a chatbot that creates real Jira tickets from plain English, with Groq as the brain.
The shape matters more than the code: the browser never touches Jira or Groq directly. A one-file Express server serves the chat UI, holds your keys in memory, and does both API calls. That single decision kills the two classic failures of vibe-coded API apps: CORS errors and API keys leaking into client-side JavaScript.
openai/gpt-oss-120b on Groq, Claude). It outputs one server.js.npm init -y && npm i express && node server.js, open http://localhost:3000.Build a lightweight local "Jira Chat" app in ONE file: server.js (Node 20+,
only dependency: express). No database, no build step, no framework.
WHAT IT IS
A chatbot web app. I type things like "create a jira ticket for the login
button being broken on mobile, high priority bug" and it creates a REAL
ticket in my Jira Cloud site, then replies in the chat with the ticket key
and a clickable link. Anything that is not a ticket request gets a normal
short chat reply.
ARCHITECTURE (do not deviate)
- server.js starts an Express server on http://localhost:3000
- GET / serves the full chat UI as one inline HTML string (no separate
files): a header, a scrollable message list, a text input + Send button,
and a Settings drawer with five fields:
1. Jira site URL (https://YOURSITE.atlassian.net)
2. Jira email
3. Jira API token
4. Jira project key (e.g. QAJB)
5. Groq API key
Clean modern styling, dark background, rounded message bubbles, my
messages right-aligned, bot messages left-aligned, typing indicator.
- The browser NEVER calls Jira or Groq directly (CORS + secret leakage).
It only calls these local endpoints:
POST /api/settings -> stores the five values in a server-side
variable (memory only; never written to disk,
never echoed back, never logged)
POST /api/chat -> { message } -> does the AI + Jira work below
- Node 20 global fetch for all outbound calls. No axios.
THE AI STEP (Groq)
- Call https://api.groq.com/openai/v1/chat/completions with the stored
Groq key. Default model "llama-3.3-70b-versatile"; put the model name in
one constant so I can switch it to "openai/gpt-oss-120b".
- Use OpenAI-style tool calling. Declare ONE tool:
create_jira_ticket(summary: string, description: string,
issue_type: "Bug"|"Task"|"Story",
priority: "Highest"|"High"|"Medium"|"Low")
- System prompt: "You are a QA assistant inside a local Jira chat app.
When the user asks to create/raise/file/log a ticket, bug, task, or
story, call create_jira_ticket with a crisp summary (max 90 chars), a
useful 2-4 sentence description expanding what they said, the right
issue_type, and priority (default Medium unless stated). For anything
else, answer briefly in plain text. Never invent details the user did
not imply."
- If the response contains a tool call: parse its JSON arguments, create
the ticket (below), then reply in chat with:
"Created <KEY>: <summary> - <siteUrl>/browse/<KEY>" (render as a link).
- If no tool call: just show the model's text reply.
THE JIRA STEP
- POST {siteUrl}/rest/api/3/issue
- Header Authorization: "Basic " + base64(email + ":" + apiToken),
Content-Type application/json.
- Body: fields = { project: {key}, summary, issuetype: {name: issue_type},
priority: {name: priority}, description in ADF format EXACTLY:
{ "type":"doc","version":1,"content":[{"type":"paragraph",
"content":[{"type":"text","text": description }]}] }
(a plain string description fails on API v3).
- On success return the "key" from the response.
ERROR HANDLING (show all of these as red bot bubbles in chat, never crash)
- Settings not saved yet -> "Open Settings and save your Jira + Groq keys."
- Jira 401/403 -> "Jira rejected the credentials: check email + API token."
- Jira 400 -> show Jira's error messages field (usually a bad project key
or a priority not available on the project; if priority causes the 400,
retry once WITHOUT the priority field).
- Groq non-200 -> "AI error" + status + body snippet.
SECURITY RULES
- Secrets live only in the server-side variable for this run.
- Never put keys in client-side JS, localStorage, URLs, or console.log.
- Add a one-line comment where a .env upgrade would go.
ACCEPTANCE TEST (make sure this exact flow works)
1. npm init -y && npm i express && node server.js
2. Open http://localhost:3000, save settings.
3. Type: "create a jira ticket for checkout coupon getting lost on double
click, high priority bug" -> a real Bug appears in the project, chat
shows "Created QAJB-123: ..." with a working link.
4. Type: "what can you do" -> plain chat reply, no ticket created.
OUTPUT: the complete server.js in one code block, then the three run
commands. Nothing else.
Where this sits on the ladder: the prompt is level 2 done professionally. Promote it to a skill when your team reuses it, or wire the same Groq + Jira calls into n8n / LangFlow when you want it running without a laptop.
A skill is one file. SKILL.md is a block of YAML frontmatter the agent reads to decide when to load the skill, followed by a Markdown body it follows once loaded. That is the whole format. Below is every part, what each one is for, and a complete skill you can copy.
The split is the point. The frontmatter is tiny and always sits in the agent's index, so it can match your request to the right skill without loading anything heavy. The body is the real instruction set, pulled into context only when the skill actually fires. Write the frontmatter for a matcher; write the body for a worker.
Fenced at the very top of the file between --- lines, written in YAML.
| Field | Required | What it does |
|---|---|---|
name | Yes | Kebab-case identifier, usually matching the skill's folder. How the skill is referenced and invoked. |
description | Yes | The trigger. A third-person summary of what the skill does and when to use it, including the phrases that should fire it. This is what the agent matches on. |
license | Optional | An SPDX id such as MIT, so others know how they may reuse it. |
metadata | Optional | A free-form map for cataloguing: author, version, and domain tags (here, stlc-phase). Used for filtering and provenance, never for triggering. |
Plain Markdown under the frontmatter. Order it so the agent reads its remit first, then how to act, then what to hand back, then what it must never do.
| Section | What goes in it |
|---|---|
| Title + information | A # Heading and one paragraph stating the skill's job and its boundary: what it produces, and what it deliberately does not do. |
| When to use | The concrete situations that should trigger it, in list form. Mirrors the description so a human and the matcher agree. |
| Workflow | The numbered steps the agent follows. Anything consequential ends in a mandatory human review gate. |
| Output shape | A template of the exact result format, so every run looks the same and is easy to diff and trust. |
| Guardrails + safety | The hard rules: never fabricate, stay in scope, keep findings traceable, require human sign-off on anything that matters. |
| When NOT to use | The situations where the skill should stay silent. This is what stops it over-triggering onto jobs it was not built for. |
| Don'ts | Explicit prohibitions, stated flatly, so the agent has no room to improvise past its remit. |
Here is a real, runnable skill, jira-requirement-analyzer, with every part above in place: frontmatter for discovery, then a body of remit, when-to-use, workflow, output shape, and guardrails.
--- name: jira-requirement-analyzer description: >- Read a JIRA ticket and judge whether it is actually ready to test. Use when a tester says "analyze this ticket", "is this story ready to test", "find gaps in JIRA-123", or pastes a user story / acceptance criteria and wants it pressure-tested. Fetches the ticket, scores it against a readiness checklist, and returns a gaps / ambiguities / risks report plus clarifying questions to send back to the author. license: MIT metadata: author: TheTestingAcademy stlc-phase: Requirement Analysis version: 1.0.0 --- # JIRA Requirement Analyzer You decide whether a story is **testable yet**, and if not, you say exactly what is missing. Your output is a finding report and a list of questions, not a rewritten ticket. ## When to use - Someone hands you a JIRA key or story text and asks "is this ready to test?" - A grooming / refinement session needs the ambiguities surfaced before estimation. - Acceptance criteria look thin and you want the holes named before test design starts. ## Workflow 1. **Fetch the ticket.** If a JIRA key is given, pull it via an available JIRA MCP tool or REST call. If neither is reachable, ask the user to paste the ticket body, never invent ticket content. Capture summary, description, ACs, components, linked issues, attachments, and fix version. 2. **Score readiness.** Walk each requirement and mark ✅ clear / ⚠️ ambiguous / ❌ missing. Check: testable acceptance criteria, defined error/empty/boundary states, roles & permissions, non-functional needs (perf, security, a11y, i18n), data & dependencies. 3. **Classify findings** into three buckets: Gaps (missing info), Ambiguities (two valid readings), Risks (what could ship broken). Rate each by impact. 4. **Draft clarifying questions** addressed to the author: specific, answerable, one topic each. 5. **HUMAN REVIEW GATE (mandatory).** Present the report as a draft. State what you assumed and could not confirm. Ask the tester to confirm or edit before these questions go to the author; do not proceed to scenario design until confirmed. ## Output shape ``` ## Requirement Analysis - <JIRA-KEY>: <title> Readiness verdict: READY / NOT READY (n blockers) Gaps [ ❌ ... ] Ambiguities [ ⚠️ ... two readings each ] Risks [ impact-rated ] Questions for the author (numbered, one topic each) --- HUMAN REVIEW GATE --- Assumptions / What I could not confirm / "Confirm before I send these to the author" ``` ## Guardrails - Never fabricate an acceptance criterion, field, or requirement: a missing item is a finding, not a blank to fill. - Do not rewrite the ticket for the author; surface the gap and ask the question. - A "READY" verdict is advisory; the author and QA lead own that call. - Keep every finding traceable to a specific line or absence in the ticket.
Want to build one end to end? The test-plan skill guide walks you through authoring one live, and the 36-skill STLC suite is a shelf of these you can lift. Where this sits on the ladder: a skill is the reusable middle rung between a one-off prompt and a full AI agent.