My original idea was to enable LLM chat-bots (in both enterprise and public domain) to structure their outputs as easily digestible UI components, instead of long text blocks. For example, when a user asks about a golf player, an agent shows a golf player card. In the process of creating these agents, I realized most of the automate-able work was not in generating the UI cards and gathering data to render them. Instead, it was in providing the LLM context on key terms, defining parameter inputs, and assigning roles, so we can trigger business logic (via agents) through prompt understanding.
I set out to create infrastructure that allowed the developer to:
-
Provide the LLM context about certain key terms their prompts should understand. When we’re at work, we commonly use terms that are foreign to the outside world, but easily understandable in the context of our daily workflow.
-
Provide the LLM context about what agents exist, what their purpose is, and what arguments they should parse out of a prompt to pass to business logic.
Our job is to handle prompt-understanding and triggering of business API by providing infrastructure to handle agent creation and management. This allows SaaS developers to transform their existing data and legacy business logic into AI agents, in order to meet user demands in the new AI-driven landscape.
sampleApp is a sample chatbot that takes in prompts and responds with UI cards. This would normally be an example of a client company which has an app that takes in text prompts, and want UI golf cards to trigger as a response. I just happend to create a sample app so that I can pretend to be the client, and have a better understanding of what part of the workflows I can automate with Renderabl FE and BE.
This is a web app for developers to help interact with the Renderabl backend. It's purpose is to allow developers to generate new function call tools, new UI components, and new context KV-entries. This data will all be ingested by the backend when the developer's app when they take in prompts and pass it to the backend, which appropriately determines which developer-provided function to call, and which arguments it should take in.
use the tsc --build command (Command + Shift + b with VSCode) to rebuild .ts to .js files in tsconfig.json
For targets in the sampleApp, run command for src/sampleApp/tsconfig.json
For the infraWebApp, run command for src/infraWebApp/tsconfig.json
then, do: npx webpack (from the root component), then start Live Server on HTML
For any styling changes on the sampleApp, run npx tailwindcss -i ./src/sampleApp/app.css -o ./src/sampleApp/output.css
infraWebApp uses materials UI, not tailwind, so this step is not necessary.
navigate to their respective directories where index.html is located, then run live-server.
Alternatively, I use the VSCode extension "Live Server" so that it's a click away.
First, start the Redis DB server with redis-server, then for the infraWebApp start the backend server with node ./dist/renderableBe/backend.js. For the sampleApp, start node ./dist/sampleApp/backend.js
For full functionality, run the infraWebApp backend (frontend optional for developers), and run sampleApp frontend and backend. My workflow:
- live-server from sampleApp/dist directory
- node ./dist/sampleApp/backend.js from sampleApp directory
- node ./dist/renderableBe/backend.js from root renderabl directory
- (optional) live-server from infraWebApp/dist directory to access/view the developer web app.
src/sampleApp/generalcards contains .tsx UI cards that I was experimenting with before I narrowed down to the golf vertical for the MVP.
src/sampleApp/golfcards contains .tsx UI cards that I've created. golfballcard.tsx was generated via a call to generateComponent in backend.ts, and golfplayercard.tsx and golftournamentcard.tsx were created manually.
/src/renderableBe contains backend.ts, which contains both the backend for the app.tsx I created, as well as backend functions that would live in the Renderabl service. I did this out of ease of just starting up one local server for development. fakedb.ts is where I put KV pairs that I would normally put in a DB.
/src/renderableFe contains renderableFeUtils.ts, which contains helper logic that builds out the functionality of Renderable FE by automating card generation and mutations (eventually).
/src/types.ts contains all the types and props.
{
"agentName": "GolfBallAgent",
"agentProps": "picture_url: string, name: string, summary:string, launch_characteristics:string, spin_characteristics: string, year_introduced:number, firmness:string, players_who_used:string[]",
"agentDescription": "A chat agent designed to show UI card components about various golf balls. Call whenever you need to respond to a prompt that asks about a golf ball. The input parameters should be the golf ball name"
}{
"agentName": "TrafficAgent",
"agentArgs": {"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"handler":{"type":"string"}, "cell":{"type":"string"}}, "required":["handler"], "additionalProperties": false},
"agentDescription": "An agent designed to show UI card components of monitoring traffic data of a specific endpoint. Call whenever you need to respond to a prompt that asks traffic data given some parameters"
}You can use Postman, but the infraWebApp also provides a UI wrapper that will call the API.
{
"prompt": "Tiger Woods 2008"
}http://localhost:5500/api/getToolGraph http://localhost:5500/api/getContext
http://localhost:5500/api/provideContext
{
"handler": [
"SampleEndpoint",
"GlobalEndpoint",
"FeatureEndpoint1",
"FeatureEndpoint2",
"FeatureEndpoint3",
],
"node": [
"global-config",
"sample-ui",
"sample-ui-extended",
"sample-touchstone",
"FeatureNode1",
"FeatureNode2",
"FeatureNode3",
],
"cell": [
"qs",
"ax",
"az",
"bu",
"FeatureCell1",
"FeatureCell2",
"FeatureCell3",
],
"component": [
"feature1",
"feature2",
"FeatureComponent1",
"FeatureComponent2",
"FeatureComponent3",
]
}If a model is changed in schema.prisma, rerun these two commands:
npx prisma migrate dev --name init and npx prisma generate







