I just realised that Agent tools with Views will display in chat

Hi KNIME,

Last weeks KNIME Summit in Munich, I bumped into @MartinDDDD.

I got a chance to ask, if he had been able to make visualisation appear in the Agent Chat or how he would solve that?

He said: Sure, just put a view node in the top layer of an agent tool workflow and tick the setting to show views in Agent Chat settings.

And behold! I could verify that, and was able to make a few test tools, that would show such views.

I learned, that the “old” Javascript views don’t work, and I needed change to the new view nodes.

But now I want to make dynamic graphs. So the Agent should be able to use a tool with a query (sql / cypher), to get a table of data, and then feed data to a tool with Apache E Chart, and dynamically make a suitable graph.

Have anyone experimented with this in an Agent setup and perhaps share some insights or tips?

3 Likes

Holy cow !

Dynamic ECharts – KNIME Community Hub

This brilliant idea just worked!

Create code for an Apache ECharts visualization in JavaScript that displays a graph showing the network of column name with column location. individual columns can be retrieved from an object called inputTable using the async getColumn function and passing the column name like this: await inputTable.getColumn("mycolumn")

Only output code, nothing else, no delimiter or anything. The code should assign an Echarts option object to an already existing variable named "option". Do not define this variable again! The table columns are the following: Name: "name" Type: String Name: "locations" Type: String
Plain Javascript Code:

Code

| const nameCol = await inputTable.getColumn(“name”); const locationsCol = await inputTable.getColumn(“locations”); const toArray = (col) => { if (Array.isArray(col)) return col; if (col && Array.isArray(col.values)) return col.values; if (col && Array.isArray(col.data)) return col.data; return ; }; const names = toArray(nameCol); const locations = toArray(locationsCol); const splitLocations = (value) => { if (value == null) return ; return String(value) .split(/[;,|]/) .map(s => s.trim()) .filter(Boolean); }; const nodeMap = new Map(); const linksMap = new Map(); const addNode = (id, category, symbolSize) => { if (!nodeMap.has(id)) { nodeMap.set(id, { id, name: id, category, symbolSize }); } }; for (let i = 0; i < Math.max(names.length, locations.length); i++) { const columnName = names[i] == null ? “” : String(names[i]).trim(); if (!columnName) continue; addNode(columnName, 0, 36); const locs = splitLocations(locations[i]); for (const loc of locs) { addNode(loc, 1, 24); const linkKey = `${columnName}__${loc}`; if (!linksMap.has(linkKey)) { linksMap.set(linkKey, { source: columnName, target: loc }); } } } const data = Array.from(nodeMap.values()); const links = Array.from(linksMap.values()); option.title = { text: “Column Name to Location Network”, left: “center” }; option.tooltip = { trigger: “item”, formatter: (params) => { if (params.dataType === “edge”) { return `${params.data.source} → ${params.data.target}`; } const categoryName = params.data.category === 0 ? “Column” : “Location”; return `${categoryName}: ${params.data.name}`; } }; option.legend = [ { data: [“Column”, “Location”], top: 30 } ]; option.animationDuration = 1000; option.animationEasingUpdate = “quinticInOut”; option.series = [ { type: “graph”, layout: “force”, roam: true, draggable: true, data, links, categories: [ { name: “Column” }, { name: “Location” } ], label: { show: true, position: “right” }, force: { repulsion: 220, edgeLength: 140, gravity: 0.08 }, lineStyle: { color: “source”, curveness: 0.1, opacity: 0.7, width: 2 }, emphasis: { focus: “adjacency”, lineStyle: { width: 4 } } } ]; |
|----|


4 Likes

Props to @MartinDDDD

2 Likes

Amazing! Glad you got that to work!

Apologies for not having reacted earlier - have been out for a few days…

If I remember our conversation in Munich you’re also after a bit of flexibility.

I have an idea on how some parts may become dynamic in the future. In the example workflows from KNIME there is one called spreadsheet doctor, which has some tools that can dynamically modify a table (filter rows / cols) and also extracting table meta data… you could re-use this tools to have your users provide verbal instructions as to how to filter any input table.

You then modify your echarts tool to have three inputs:

  1. table input → the modified table
  2. Table metadata (as string variable - potentially converted to JSON, from the table meta data tool)
  3. User input on what the columns of the modified table contain, preferences on how to look at the data

You then stitch 2 & 3 together in a prompt and maybe give in LLM prompter 2 examples of input and output…

Will probably need some experimenting… but could be a very flexible solution!

2 Likes