Building a chatbot is easy enough today. You can create a text input, send the message to an LLM API, stream the response back to the browser, and call it an AI application. The difficult part starts when you want that chatbot to behave more like an actual assistant. Once you expect it to remember previous conversations, access external services, perform actions, keep credentials secure, and remain reliable after deployment, the project becomes much more than just an interface around an LLM.
That is what I wanted to explore with my latest project. I am building a personal AI assistant that can eventually connect to an external system I call balw21. The goal is not simply to let the user ask questions. I want the assistant to keep useful context, decide when it needs external information, call controlled backend functions, and then use the result to answer or complete a task. I also wanted the deployment side to stay manageable. I did not want to create a completely separate infrastructure setup for the frontend, backend, conversation storage, model gateway, and AI runtime before I could even test the idea properly.
This is why I decided to use Tencent EdgeOne Makers.
What interested me about EdgeOne Makers was not just the fact that it can host a website. The platform also provides components that are useful for AI applications, including an Agent runtime, model access, serverless functions, persistent storage, conversation state, custom domains, and security features. For a project like mine, that means the frontend and the AI backend do not have to feel like two unrelated projects deployed to different services.
Moving beyond a normal chatbot
The first design decision was deciding what the assistant should actually do.
A normal chatbot receives a prompt and returns generated text. My project needs more structure than that because some user requests may require information that the model does not already have. If a user asks the assistant to check something stored inside balw21, the model should not invent the answer or somehow receive unrestricted access to the entire service. The assistant needs a controlled way to retrieve that information.
The way I prefer to think about this is to separate reasoning from execution. The Agent can understand what the user is asking and decide that a certain tool is required. The actual tool then calls backend code that I control. That backend code handles authentication, validates the request, talks to balw21, and returns a structured response. The Agent can then turn that response into something understandable for the user.
This separation matters because an LLM should not become the security layer of the application. If an operation requires authorization, the authorization should happen in code. If an API expects specific parameters, the parameters should be validated in code. If an action changes important data, the backend should decide whether that action is actually allowed. The model can decide which approved tool is relevant, but it should not be trusted to bypass the normal rules of the application.
This also makes the project easier to debug. If something goes wrong, I can determine whether the problem came from the model choosing the wrong tool, the backend returning the wrong data, or the model misunderstanding a correct tool result.
Why I used the Agent runtime
For a very simple AI application, a normal API route is often enough. The browser sends a request to the server, the server calls a model, and the model response is returned to the browser. That architecture is clean and works well for many applications.
A personal assistant becomes more complicated because one user request can require several steps. The model may need to inspect the request, decide to use a tool, wait for the tool result, interpret that result, and possibly call another tool before generating the final response. That process is better represented as an Agent workflow than as a single model completion.
Tencent EdgeOne Makers includes a dedicated Agent runtime for this kind of work. This is useful because the project does not have to treat every AI interaction as a small isolated API call. The Agent can manage its execution state, work with tools, and continue a conversation using an existing conversation identifier.
For my project, this gives the AI part of the application a clearer responsibility. The Agent handles language understanding, decision making, and tool selection. The rest of the application still behaves like normal software. Backend functions perform deterministic operations, storage systems persist data, and external APIs remain behind controlled interfaces.
That division is something I want to keep even as the project becomes more capable.
Conversation memory is not just chat history
One feature I consider essential for a personal assistant is memory.
At first, this sounds simple. Save the messages somewhere and load them again later. In practice, there are at least two separate problems.
The first problem is storing the visible conversation. If the user refreshes the page or returns later, the application should still be able to display the previous messages. That is mostly a persistence and user interface problem.
The second problem is maintaining enough context for the Agent. The model needs to know what previous messages referred to. If the user says, "Use the same setting as before," the assistant needs enough previous context to understand what "before" means.
EdgeOne Makers provides persistent conversation storage for Agents through the conversation context. A conversation can be associated with a conversation identifier, allowing later requests to continue the same state even if they are handled by a different runtime instance.
This matters because serverless systems are not designed around the assumption that one process will stay alive forever. Storing conversation data only inside a local variable would work during development and then fail unpredictably after deployment. Once that runtime instance is recycled, the memory disappears with it.
Persistent conversation state avoids that problem. The application can treat a conversation as something that survives beyond a single execution.
However, persistent storage does not mean the application should send the entire history to the model forever. A long-running assistant may eventually accumulate hundreds or thousands of messages. Sending every message on every request would waste tokens, increase latency, and eventually exceed the context window of the model.
A more practical design is to keep recent messages in full and compress older information into a summary or another long-term memory format. The application can preserve useful facts without repeatedly sending the complete conversation history.
This is also where application-specific decisions become important. A personal assistant may want to remember preferences, previous tasks, and long-running projects. A customer support bot may instead care about ticket history and unresolved issues. A coding assistant may need technical decisions, repository details, and previous errors. Memory is not just a database feature. It is part of the product design.
Using Makers Models without tying everything to one provider
Another problem that appears quickly in AI development is model dependency.
The first version of an application is often written directly around one provider's SDK. That is convenient at the beginning, but it can make experimentation harder later. If model calls are scattered throughout the codebase, switching providers may require changing authentication, request formats, streaming logic, error handling, and response parsing in several places.
Tencent EdgeOne Makers provides Makers Models as a model gateway. The useful part for me is that the rest of the assistant does not need to care as much about which provider is behind every request.
This makes model experimentation more practical. A stronger model might be useful for complicated reasoning, while a faster model could be enough for lightweight classification or short responses. Different models may also have different pricing, latency, or context window advantages.
I do not want the overall architecture of the personal assistant to depend too heavily on one model. Models change quickly. The application around them should be more stable.
The same principle applies to prompts. I prefer keeping prompts and model configuration close to the Agent layer instead of mixing them with unrelated application code. That way, changes to the reasoning behavior do not require touching the rest of the backend.
Connecting balw21 safely
The balw21 integration is where this project becomes more interesting than a normal chatbot.
I do not want the model to receive unrestricted credentials or construct arbitrary requests against the service. Instead, I want to expose specific capabilities as tools.
For example, the Agent might have a tool that retrieves a particular type of user information. The Agent knows what the tool does and what parameters it accepts, but the actual request to balw21 happens inside backend code.
That backend can read credentials from server-side environment variables, validate parameters, enforce permissions, handle timeouts, normalize the response, and return only the information the Agent needs.
This gives me much better control over what the assistant is capable of doing.
It also reduces the chance that an unexpected prompt causes the model to call an endpoint it was never supposed to access. Rather than giving the Agent a generic network request tool, I can give it small, purpose-built tools.
The difference is important. An unrestricted tool gives the model a capability. A narrow tool gives the application a capability that the model is allowed to request.
For me, that is a safer way to build agentic applications.
Where Edge Functions and Cloud Functions fit
EdgeOne Makers provides both Edge Functions and Cloud Functions, and I would not treat them as interchangeable.
Edge Functions make sense for lightweight logic that benefits from running close to users. Request processing, small authentication checks, routing, or simple transformations are good examples of the kinds of tasks that can fit naturally at the edge.
Cloud Functions are more appropriate for heavier backend work. If a request needs more processing time, additional runtime capabilities, or more complex server-side logic, a Cloud Function is usually a better place for it.
For the personal assistant, I would choose the runtime based on the actual workload rather than using one type of Function for everything.
A lightweight request validation step may belong at the edge. A more complicated integration with balw21 may be easier to maintain inside a Cloud Function. The Agent itself has a separate responsibility because its execution can involve multiple model and tool calls.
Keeping these workloads separate also makes the codebase easier to understand.
Storage needs more than one strategy
Another part of the project is deciding where different kinds of data should live.
Not everything belongs in conversation storage.
Small pieces of application state, such as preferences or configuration values, can fit well in key-value storage. Files, images, documents, or other larger objects are better suited to object storage.
Conversation messages belong in conversation storage because they are related directly to an Agent session.
This sounds obvious, but it becomes easy to misuse storage when a project grows quickly. Developers sometimes put everything into the first database or storage service they already have, even when the access pattern does not match the data.
For a personal assistant, I want to keep these categories separate from the beginning. User preferences should not be stored in the same way as a large uploaded PDF. A conversation summary should not be treated like a static file. A document uploaded for analysis should not be inserted directly into every future prompt.
Good storage decisions make later features easier to build.
Tool access and sandboxing
One of the more powerful parts of modern Agents is their ability to use tools.
An Agent can potentially execute code, interact with files, use a browser, or run shell commands inside a sandboxed environment. That can turn a chatbot into something much more capable.
For example, a future version of my assistant could receive a file, analyze its contents, run code to process the data, and explain the result.
That is useful, but it also changes the risk profile of the application.
A model that only generates text has limited ability to affect the outside world. A model with tools can perform actions. The more powerful the tools are, the more carefully they need to be restricted.
I do not think a good Agent should automatically receive every available capability.
If the assistant only needs to retrieve a certain type of information from balw21, then it should have a tool specifically for that operation. It should not get unrestricted shell access or generic network access unless there is a real reason for it.
This is one of the main lessons I am following while working on the project. The goal is not to give the Agent as many tools as possible. The goal is to give it the smallest set of tools that lets it complete useful tasks reliably.
Deployment is only part of the advantage
The obvious attraction of a platform like EdgeOne Makers is simpler deployment, but I think the more important advantage is reducing fragmentation.
Without a platform like this, an AI project can quickly become a collection of unrelated services. The frontend may live on one provider, the backend on another, conversation data somewhere else, model access through another API, object storage in another account, and observability in yet another dashboard.
That architecture can absolutely work, and larger systems may eventually need that level of separation. For a smaller project, though, it creates a lot of overhead before the core product has even proven itself.
Using EdgeOne Makers means I can keep the website, Agent, serverless logic, storage, deployment, domains, and related configuration closer together.
That lets me spend more time testing whether the assistant is actually useful instead of spending most of my time connecting infrastructure.
Observability becomes important very quickly
Agent applications are harder to debug than normal request-response applications.
A user may send one message, but the system might perform multiple model calls and tool executions before returning an answer. If the final result is wrong, the visible response alone does not tell me where the mistake occurred.
The model might have selected the wrong tool. The correct tool might have returned an error. The tool might have returned correct data, but the final model response might have misinterpreted it.
This is why tracing becomes important once an Agent grows beyond a simple demo.
Being able to inspect what happened during a run makes it easier to understand the behavior of the system. Logs alone are useful, but tracing the sequence of operations gives much better context when several components are involved.
For my project, I consider this part of the development workflow rather than something to add after the product is finished.
Designing for failure instead of only the demo
Another lesson from building AI applications is that the happy path is not enough.
It is easy to demonstrate an assistant when every service is working perfectly. The user sends a request, the model responds, and everything looks impressive.
Real applications need to handle the cases where the model times out, the external API is unavailable, the conversation fails to load, a tool returns malformed data, or the user sends the same request twice because the interface appeared to freeze.
The backend should distinguish between an empty result and a failed request. Sensitive operations should avoid being executed twice because of retries. The user interface should stop waiting eventually and show a useful error instead of displaying a loading indicator forever.
These are normal software engineering problems. Adding AI does not make them disappear.
In some ways, AI makes them more important because there are more moving parts involved in producing a single answer.
Tencent EdgeOne Makers can simplify the infrastructure around the application, but the developer still needs to design how the application behaves when something goes wrong.
I think that is the right trade-off. The platform can provide the infrastructure primitives, while the developer remains responsible for the behavior and reliability of the product.
What I learned from building this
The biggest change in my thinking is that I no longer see the LLM as the application.
The model is one component.
A useful personal assistant also needs persistent state, backend logic, safe tool access, storage, authentication, error handling, deployment, and observability.
Once the project is viewed this way, the architecture becomes much easier to reason about.
The Agent should handle language and decisions. Functions should handle controlled application logic. Storage should persist the right type of data. External services should stay behind narrow interfaces. The frontend should present the result clearly without exposing secrets or internal infrastructure.
Tencent EdgeOne Makers has been useful for this project because it gives me many of those pieces in one environment.
The platform does not automatically make the assistant good. It still depends on how I design the memory, tools, prompts, permissions, and backend integration.
What it does is remove enough infrastructure work that I can spend more time on those decisions.
What I want to build next
The next step is making the connection with balw21 more useful and more structured.
I want the Agent to be able to request specific information through controlled tools without receiving broad access to the external service. I also want to test longer conversations and see how much context should remain in recent message history compared with summarized memory.
Another area I want to explore is model selection. Different tasks may not need the same model, so using a gateway makes it easier to experiment without redesigning the whole application.
File-based workflows are also interesting. A personal assistant becomes much more useful if it can work with documents and other user-provided data rather than only text typed into a chat box.
The important part is that I do not want to add all of those capabilities at once.
I would rather add one useful capability, make it reliable, understand how it fails, and then add the next one.
That has been the main takeaway from this project so far.
AI Agents are exciting, but the best results do not come from giving a model unlimited tools and hoping it figures everything out. A better approach is to build a small, understandable system where each capability has a clear purpose and a clear boundary.
For me, Tencent EdgeOne Makers is useful because it gives me a practical place to build that kind of system without spending most of the project setting up infrastructure first.
Top comments (0)