Recently I've been experimenting with running a local Llama.cpp Server and looking for 3rd party applications to connect to it. It seems like there are have been a lot of popular solutions to running models downloaded from Huggingface locally, but many of them seem to want to import the model themselves using the Llama.cpp or Ollama libraries instead of connecting to an external provider. I'm more interested in using this technology as a server so that I start it once and allow clients to connect to it without needing to shutdown and go through the long, resource intensive, start-up process of each application. One of the applications that I've found great for chatting with in my setup is AnythingLLM.
AnythingLLM can connect to multiple providers, including Llama.cpp's llama-server (As an OpenAI compatible API), Ollama, OpenAI, Anthropic, Gemini, and others. Another cool feature of AnythingLLM is that it lets you use the LLM as an agent.
Agents are LLMs that have access to tools, so that they can do more than just chat with the user. You can ask an Agent to go execute some command, perhaps a web search or image generator with some parameters. This is powerful. With an agent, you can have a conversation with the LLM about something, and then say "Go do something with this information". Imagine telling your LLM to get today's headlines from your favorite news source, review for anything related to some specific subject that interests you and then email the headlines to you!
Out of the box, AnythingLLM has a few agents built in, including a chart generator, a web search, a web scraper, and SQL connector to query databases. Those are awesome. BUT, more recent versions of AnythingLLM let you create your own agents with JavaScript/Node.js!
If you know how to interface with APIs, this can be a game changer.. you can tell your LLM to do anything that you can access via a REST endpoint. But you know what would be even better? Not needing to do the API work yourself. There are automation services that do all the API work for you and let you automate and chain tasks from one API to another, such as Make.com, IFTTT and Zapier. These automation services offer a webhook trigger that lets you easily pass some parameters to a unique URL to kick off automations using pre-built connections to popular services and utilities to enable such actions as posting to X or Instagram or update a Google Sheets spreadsheet, etc.
Make.com
For my example I wanted to have my LLM agent update a Google Sheets spreadsheet with contact information. Make.com has both a connector to do Google Sheets connections and has a webhook trigger. Make.com has lots of other connectors too, so you will want to explore Make.com's library of connections to do some really interesting stuff.
Before we set up our agent, let's get the Make.com side of things set up.
-
First we'll need a spreadsheet to insert our date into. Go to Google Sheets and create a new spreadsheet to store the Name, Email and Phone Number of contacts.
-
Next we'll create a new Scenario on Make.com. Our first connector will be the Webhook. A webhook is just a URL intended to receive data (instead of showing a web page). You can just go with the default settings and give it a name.
Make.com will generate a unique URL for you to use. Copy the URL down. We'll need it to continue the configuration and for the agent setup later.
-
The webhook will need to receive an actual call to know what data to expect. Using curl, let's send it a JSON payload of the 3 fields from our spreadsheet and some test data.
curl -X POST https://hook.us2.make.com/testqrd3j8469g856t16hp9l95yeowv9 -H "Content-Type: application/json" -d '{"name":"Jon Smith","email":"jsmith@example.com","phone":"555-555-5555"}'
The Make.com interface should reflect that it received the call immediately.
Next add a connector for Google Sheets by clicking the big plus sign to the right of our new Webhook connector. You'll be asked to connect your Google account, select the document from your Google Drive and select the sheet name (probably Sheet1).
-
With the Google Sheets connector added and linked to your spreadsheet, you'll see a section for Values. These values can be received from earlier connections in your Make.com scenario - in our case, the Webhook. For each of Name, Email and Phone, select the Webhook values shown.
Click OK to complete the Google Sheets connection setup.
Our Make.com scenario is now complete. To save it click "Run Once" on the bottom left.
Once the scenario is saved, turn on "Immediately as Data Arrives" on the bottom. This will let let your webhook update your spreadsheet even when you are not signed into Make.com.
Run the curl command from above again with a some different data. You should see your spreadsheet update almost immediately and we'll know that your webhook is working and ready for our next steps.
Before we continue, do keep in mind that giving an LLM the ability to do things in the real world is both powerful and dangerous. Think carefully about potential consequences before giving it access to important documents and tools.
With that, let's get started with the agent.
AnythingLLM
If you don't already have it, download the AnythingLLM desktop application for your platform here. In my examples I'll be using my Macbook Pro to run AnythingLLM and connecting to llama-server running on an Arch Linux server with the Meta Llama 3.1 Instruct model (70B). However, you can do all of this just by linking AnythingLLM to the OpenAI API with an API Key. I will not go into the details of the initial setup of AnythingLLM in this post, but once you get it up and running, have a workspace created and can chat in the workspace with your LLM, you are ready to continue to the next step. Consult the AnythingLLM Documentation for assistance.
Agent Configuration
Once you have a Workspace running, go to the workspace settings (Gear icon to the right of the workspace name on the left side of your screen). Click the Agent Configuration tab at the top and select a Workspace Agent LLM Provider. This can be the same LLM provider you use for chat.
Next click Configure Agent Skills. This screen should have all of the built-in agent skills listed, including RAG and website scraping. You can optionally turn on Generate charts, Web Search and a couple others that you might find useful. At the bottom might be "Custom Skills", which will be empty until we create one.
-
Try out one of the built-in agents to get an idea of how they work. To call an agent function, prefix your request with @agent. For example, ask your LLM to check the top tech headlines on CNN:
Writing a Custom Agent Skill
Now that you know how to use an agent and we have Make.com ready to go to communicate with our future agent, let's get get the agent written.
Find your
agent-skills
directory. On Mac, this is in your home directory under: Library/Application Support/anythingllm-desktop/storage/plugins/agent-skills , but check the documentation for your platform.In agent-skills, make a new directory for your agent:
mkdir sheet-update-agent
-
Define your agent in plugin.json.
Create a new file called plugin.json inside the sheet-update-agent directory and paste in the below. I'll discuss what all this means after.
{ "active": true, "hubId": "sheet-update-agent", "name": "Update Google Sheet", "schema": "skill-1.0.0", "version": "1.0.0", "description": "Update Google Sheet via Make.com Webhook", "author": "@drunnells", "author_url": "https://github.com/drunnells", "license": "MIT", "setup_args": { "postUrl": { "type": "string", "required": true, "input": { "type": "text", "placeholder": "https://hook.us2.make.com/your-custom-url", "hint": "The URL to send the post request to" }, "value": "" } }, "entrypoint": { "file": "handler.js", "params": { "name": { "description": "Contact name", "type": "string" }, "email": { "description": "Contact email address", "type": "string" }, "phone": { "description": "Contact phone number", "type": "string" } } }, "examples": [ { "prompt": "Add Bob Smith's contact information to the contact spreadsheet - Bob Smith, bsmith@example.com, 123-456-7891", "call": "{\"name\": \"Bob Smith\", \"email\": \"bsmith@example.com\", \"phone\": \"123-456-7891\"}" }, { "prompt": "Here is Jane Doe's info: jdoe@sample.com, 555-555-5555", "call": "{\"name\": \"Jane Doe\", \"email\": \"jdoe@sample.com\", \"phone\": \"555-555-5555\"}" }, { "prompt": "Add Billy Exampleman to my contacts, his phone number is (444)333-2211 and email billy_e@test.net", "call": "{\"name\": \"Billy Exampleman\", \"email\": \"billy_e@test.net\", \"phone\": \"444-333-2211\"}" } ], "imported": true }
We'll break above down into 4 sections so you know what each is for.
Main plugin definition / other_properties - This is where the plugin name, details and author info is.
You'll need to make sure to update:
- hubId - This should match the directory name inside agent-skills
- name - The name of your custom skill / agent
- description - A short description about your skill
- author - Your author id
- author_url - A link to more information about you
Setup Args - This is how you define the configuration screen for your agent. In our case we let the user paste in their Make.com webhook URL. The values here will be exposed to your Javascript as the runtimeArgs[] array. You will observe that the empty "value" inside setup_args will become populated with the saved data once it is set by the user.
Entrypoint - Every parameter that you want to send to the JavaScript function for your agent is set here. Notice that handler.js is the filename. For our example, we'll be passing along the name, email and phone of each contact from the LLM conversation.
Examples - The AnythingLLM documentation says that you should provide 1-3 examples of how the user might indicate the parameters that will be sent to your JavaScript function.
-
Write your agent's javascript to call the webhook in handler.js and put it in the same directory with your plugin.json. The below JavaScript is just a function that takes the passed in name/email/phone parameters and does a post to our webhook URL (this.runtimeArgs["postUrl"]) set by the user in the AnythingLLM Custom Skill configuration screen.
module.exports.runtime = { handler: async function ({ name, email, phone }) { try { this.introspect(`Received Parameters: ${JSON.stringify({ name, email, phone })}`); this.introspect(`Runtime Arguments: ${JSON.stringify(this.runtimeArgs)}`); const postUrl = this.runtimeArgs["postUrl"]; if (!postUrl) { return "Error: postUrl is not configured."; } this.introspect(`Attempting to post to webhook: ${postUrl}`); if (!name || !email || !phone) { return "Error: Missing required parameters. Please provide name, email, and phone."; } const response = await fetch(postUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: name, email: email, phone: phone }) }); if (response.ok) { return "Document updated successfully!"; } else { return `Failed to update document. Status Code: ${response.status}`; } } catch (e) { return `Failed to update document. Error: ${e.message}`; } } };
-
Setup your new custom agent in the AnythingLLM UI.
a. Go to the gear icon to the right of your workspace. Click Agent Configuration.
b. Select the Workspace Agent LLM Provider - Your Agent will not work until you do this! I just select the same LLM that I chat with in my workspace, but note that not all LLM models are equally good at being agents.
c. Click Configure Agent Skills
d. You should see your new skill under Custom Skills at the bottom.
e. Click our new "Update google sheet" skill. It should have the postUrl field that we defined in our plugin.json. This is where we'll paste our Make.com webhook URL.
-
Now it's time to test! Return to a chat in your workspace and type something like:
@agent update my contacts with Thomas Jupiter - tjup@fakeemail.com - 777-888-9999
If all went well, you'll see the new row in your Google Sheets spreadsheet and this in the AnythingLLM chat:
Top comments (0)