The Testing Academy · Class Notes Saturday, 12 September (IST)
Live class · study guide

A bug triage agent on a canvas, then the same flow behind curl, Postman and a React page

The second Langflow session, and the one where a flow stops being a demo. A bug triage agent built from four components, then the hard part: fetching the real ticket from Jira over REST, which fails until you learn the auth header wants base64 of email and token rather than the token. Then a parser, a prompt template that makes the ticket key dynamic, and the payoff, that every Langflow flow is already an HTTP endpoint you can call from Postman, from Claude Code, or from a React page you generate in a minute.

By Pramod Dutta, The Testing Academy. Study notes from the live AI Tester Blueprint 4x workshop, rebuilt from the session recording and the batch repository, which received the four exported flows, the custom component and the React front end at the end of it. The Eraser deck was not reachable while this page was written. The last third of the transcript is a Devanagari transliteration of English, which is readable but easy to mis-transcribe, so every endpoint, header, field name and code sample here is quoted from the repository rather than from the recording. The debugging that failed live is reported as it happened, including the two things that were still broken when the session ended.

01

Where this sits

The batch has n8n behind it and one Langflow session. Today is the second, and it opened on positioning rather than on the canvas.

The argument, in short. Langflow is open source, and it is already in production: two projects at the instructor's own company, one for RCA and one for flaky tests, running around the clock. It will arrive at your company too, and the person who brings it should be you. Not because the tool is hard, but because opportunity follows visibility. If your manager does not know you can build this, the problem statement goes to someone else. The phrasing from class: learn it, build it, then show the proof of concept.

One learner had already done exactly that, a defect insight agent with clustering and a chat interface that leadership is now using. That is the bar.

A promise was extracted from the room: three agents, today. An RCA bot, a bug triage agent and a flaky test finder. The instructor's count was that only nine people had posted on the last task, and he said plainly that this is the part that hurts. Meeti is sending a form to track which agents each person has actually built in n8n and Langflow.

02

The canvas, and what is on it

Langflow is a drag-and-drop builder over the same idea as n8n: trigger, action, result. The panel is on the left rather than the right, and pressing Escape gets you from the chat view back to the canvas.

What is in that panel, and worth knowing before you build:

  • Inputs and triggers. Chat input, chat output, and a webhook, which starts the flow when something makes a request to its URL.
  • Data. API request, SQL, URL fetch, file access, web search.
  • Models. DeepSeek, Groq and the rest, each already a component. Nothing to code.
  • Guardrails, which screen prompts for PII, jailbreaks and offensive content.
  • Tool mode. Any component can be switched into it, which is how it becomes a tool an agent can pick up. That is the brain, memory, tools shape from the earlier class.
  • Custom components, where you write Python if nothing on the shelf fits. Section 8 needed one.

Under discover more there are components published by other companies, Jira and Atlassian among them, free. The Jira one runs through Composio, which is a paid service with a free tier, so the class took the other route and called the REST API directly.

03

Version one: four components

The first build ignores Jira completely and proves the idea:

Text
Chat input  ->  DeepSeek  ->  Chat output
                  ^
            system prompt: you are a QA bug triage assistant

Paste a real bug report into the playground and it comes back with a classification, severity, priority, QA comments and a triage suggestion. Working, and useless, because a human still has to fetch the ticket and paste it.

The prompt template is worth adding even here. The system message can live on the model component, but pulling it into its own prompt template component makes the flow modular: when the prompt changes you edit one box instead of opening the model's settings. That template becomes load-bearing two sections from now.

04

Fetching the ticket, and the auth trap

Replace the chat input with an API request component pointed at Jira, and the first attempt returns an HTML page rather than JSON. So does the second. This took a real chunk of the session, and the answer is worth more than the flow:

Jira's REST API does not want your API token in the header. It wants HTTP basic auth, which means the header value is the word Basic followed by the base64 encoding of email:token, not the token on its own. Asked in class whether the token is the Jira API token: no. It is the combination, your account email and the token, joined by a colon and encoded.

Terminal
# the value the Authorization header actually wants
printf 'you@example.com:YOUR_API_TOKEN' | base64
Text
GET  https://<your-site>.atlassian.net/rest/api/3/issue/VWO-49
Authorization: Basic <that base64 string>
Accept: application/json

Two practical notes from the debugging. Check it in Postman first: importing the curl into Postman is how the class established that the credentials were fine and the problem was elsewhere. And Postman strips the auth header on import, so re-add it before concluding anything.

ONE FLOW, SIX COMPONENTS Chat inputVWO-51 Prompt templatebuilds the URL API requestGET, Basic auth ParserJSON to text Prompt templateticket + triage rules DeepSeekdoes the triage Chat outputthe verdict The parser exists because an API response is JSON and a model input is text. Nothing connects those two directly. Jira lives behind the API request; the two prompt templates are the only places you edit wording.
Six components. The two that trip people up are the parser, which is a type conversion, and the first prompt template, which is what makes the ticket key dynamic.
05

Why the parser is not optional

The API response is JSON. The model input is text. Langflow will not let you wire one into the other, and that is a type rule rather than a bug. The parser sits between them and turns the response into something a prompt can carry.

Once parsed, the ticket goes into a prompt template as a variable:

Text
You are a senior QA analysing a bug report.
Give severity, priority and QA comments.

Bug report:
{result}

Run it and the prompt that reaches DeepSeek contains the whole Jira JSON, the model reads it, and the triage comes back for that specific ticket.

06

Making the key dynamic

The flow still had the ticket ID hardcoded in the URL, which the room spotted immediately. The fix is small and it is the whole trick:

Text
https://<your-site>.atlassian.net/rest/api/3/issue/{issue_key}

{issue_key} in single quotes, not double, makes it a variable on the prompt template, and the chat input feeds it. Send VWO-50, the URL becomes the VWO-50 issue, and the triage comes back for VWO-50. Send VWO-51 and it does it again.

The repository keeps both versions on purpose, which makes the difference easy to see:

Flow Where the ticket comes from Usable from a UI?
01_LangFlow_Simple_HelloWorld nothing, chat input straight to the model the hello world
03_AI4X_003_..._Agentic hardcoded VWO-49 in the URL no, the input is ignored
004_AI4X_004_..._Via_UI chat input feeds {issue_key} yes

Flow 03 has no chat input at all, so anything you send lands nowhere and every call returns the same VWO-49 triage. That is the bug the dynamic version fixes.

07

The flow is already an API

This is the part that changes what a flow is for. Every Langflow flow is served at POST /api/v1/run/<flow-id>. Open API access on the flow, create a Langflow API key, and you have a curl.

FOUR CALLERS, ONE ENDPOINT The playground Postman Claude Code, Copilot Your React page POST /api/v1/run/<flow-id> x-api-key: sk-... { input_type: "chat", input_value: "VWO-51" } The flow runs Jira, parser, DeepSeek, verdict it is up as long as Langflow is Nothing is published or deployed. The flow was already reachable the moment you saved it.
The canvas is a building tool. The endpoint is the product, and it is there from the start.

The call, as the repository's own front end makes it:

JavaScript
const res = await fetch('/api/run', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    output_type: 'chat',
    input_type: 'chat',        // must be "chat"
    input_value: 'VWO-51',     // the ticket key; there is no "issue_key" field here
    session_id: 'ui-1a2b3c',
  }),
});
const data = await res.json();
const text = data.outputs[0].outputs[0].results.message.data.text;

input_value carries the ticket key, not a field named issue_key. The {issue_key} variable exists inside the prompt template; from outside, the flow has one chat input and the value goes in as input_value. Getting this wrong is the difference between a working call and the same VWO-49 answer every time.

08

A page in front of it

Pasting the curl into a coding agent and asking for "a lightweight React UI with a run button" produced a working front end in a couple of minutes: type a ticket key, press Run, read the triage. That is now in the repository at chapter_09_LangFlow/ui_bugtriage/.

The part worth reading before you deploy your own, straight from the comments in that code:

A Vercel function cannot see your laptop. The front end calls its own /api/run, which forwards to Langflow with the API key kept server-side. If LANGFLOW_URL is set to http://localhost:7860 on a deployed site, localhost there means the function's own container, not your machine. Expose Langflow with a tunnel (cloudflared tunnel --url http://localhost:7860) or host it, and use that address. The repo's proxy checks for exactly this and returns a readable error instead of a timeout.

09

The custom component, and the limit that forced it

The last build tried to add Claude Code as the brain via an API request component, and it would not connect. The reason is the same type rule as the parser, in the other direction:

Asked live, and answered by the model the class was debugging with: the body port on an API request is a data port, while a prompt template's output is a message. Langflow only lets you snap a message wire into a message port, so that connection is not possible at all. The way through is a custom component, a small piece of Python that takes the message, builds the JSON body itself, and makes the call.

DeepSeek generated that component, it was pasted into a new custom component on the canvas, and it worked on the first run. The code is in the repository as CustomCommandCode.json.

Two things were still broken when the session ended, and they are reported here as they were: the curl-based version of that same call kept returning empty content, and the equivalent flow through the plain URL form worked instead. The instructor said he would fix it and share it rather than leave it hanging.

The debugging was left in on purpose. In the instructor's words, this is how you actually do it: you ask, you check in Postman, you read the error, you try the other route. The session was deliberately not edited into a clean demo.

10

Tasks and announcements

Today

  • Build three agents. An RCA bot, a bug triage agent, and a flaky test finder. Minimum three, posted to the SDET club thread.
  • Post them on LinkedIn. Your n8n flows and your Langflow flows.

The next build, with a hint

  • A flaky test case finder. The hint given in class: use the read file component to ingest a JSON test result file, then hand it to the model the same way the ticket was handed over here. Two files, compared, is the shape.

Announcements

  • A mandatory live test covering everything in n8n and Langflow so far.
  • A separate video on installing Langflow with Docker is being recorded rather than done live. If you are on Docker already, use a volume so your flows survive a restart.
  • The exported flows and the custom component are being shared with the batch.
  • On spend: five dollars on DeepSeek lasts months at this usage. Groq is free, and Google's lighter Gemini models have a free tier. The brain does not matter much here; the flow does.

Repository: AITesterBlueprin4x received chapter_09_LangFlow/ with the four exported flows (hello world, the agentic hardcoded version, the UI version and the custom Claude Code component) and the ui_bugtriage React front end with its Vercel proxy.