Transcription: OpenAgents Episode 132 - v3 Core Feature
June 9, 2026 ยท View on GitHub
Source: https://x.com/OpenAgentsInc/status/1846967946947776716 Wiki source: https://raw.githubusercontent.com/wiki/OpenAgentsInc/openagents/Video-Series.md Media title: OpenAgents - Episode 132: v3 Core Feature We design and start building our core f... Upload date: 20241017 Transcription model: gpt-4o-mini-transcribe Generated at: 2026-06-01T16:02:00Z
Machine-generated transcript. Review speaker labels and wording before using this as quote-grade source material.
[00:00] Speaker: Okay, we have a basic landing page here that's live at openagents.com. And we've got more to do with like building a blog and like opt-in forms and stuff. We'll kind of repeat the same process we did in the last video for components that will be also useful in OpenPress. But in this video, I want to start by going directly at like, what is the single core feature that we're going to be building? What's the single core feature that like runs OpenAgents? The core feature is you ask for something and an agent makes it happen. Could be anything. In the beginning, it's going to be site building. And the cool thing about that is we can use the site builder to help build OpenAgents and OpenPress and the other projects that I want to get sites built for. So we're going to focus on site builder functionality initially, but we're also going to build it in a way that it's going to be extensible through community plugins. You can see earlier in the series, we did a lot of work with plugins and we had kind of monetized plugins working with our version one of our app. We've got to kind of refactor some of the ways that we implemented that to be simpler, but plugins, plugins, plugins are how we're going to expand this into multiple use cases and get people paid to help build agents and plugins. But we're going to drive out site builder functionality first. Okay, so how we'll implement that, and we're going to drive this out via test driven development in this video. Very simple. A user will send a message to a thread. That's how we had version one of our OpenAgents. We had a list of threads on the left and you send chats, messages to the thread. Cool. Not immediately, but we want threads to be able to be organized into projects and teams. And then we want the system to take action, an agent to take an action and add a message to the thread. LLM tool calls with GitHub APIs is kind of what powers that. And that's the functionality that kind of powers the coding agents on V2 is basically a cloud sonnet LLM that has access to tools and can do things in a loop. Okay, so we're going to drive this out via TDD and hopefully by end of today, we've got something that you can interact with meaningfully on the OpenAgents website. I don't yet know if we're going to be dependent on cloud and therefore we'll want to charge for it right away. But we'll handle payment stuff secondarily. So let's get this built. We have, again, a pretty fresh, clean, new Laravel application. We're doing Laravel, Tailwind, and no build to JS. I think at some point what we may want to pull in HTMX, but we're going to just kind of see how far we can get on just doing the basic model setup. Okay, so I want to do TDD. Let's write some tests. And let's go get OpenAgents here up to speed here. So OpenAgents Inc. OpenAgents. We're on a branch called Core. So here's what we're building. I'll set up Laravel models, migrations, and then ask you to help with stuff. For now, just say acknowledged or ask any simple question you have. So I think we'll start with the feature test and then drop down into user test, unit testing as needed. So what should we call this feature? I don't even know. We'll call it core functionality test. So there's a typo there, but I don't even care. So here's what we're going to do. We're going to say, I want you to write test tests. Look at boom. For now, write tests, feature tests for all of the above functionality. We'll do unit tests separately in here. Threads can be organized into projects. Hmm. That's not bad. Additional parameters. No, it already exists. Cool. So we've got user consent message in a thread. System can add message to a thread. Threads can be organized into projects. Threads can be organized into teams. System can make LLM tool calls with GitHub API. Hey, that's not bad. Okay, let's get all of these things passing. Let's actually first have it create these first create those services in app services and use mock data for now. And then we will go and add the models for these things. We already have user and then we're going to use the syntax PHP artisan make model message. Put this in app MF message, thread, project and team. Import services. Okay, so does it matter what order we do this in? I think thread. Sometimes with the relationships, it matters. Team can have many users. A project can belong to a team. A thread can belong to a project and or a team. A message can belong to a message. A message can belong to a thread. Okay, let's do this. MF. Did I mess up adding two hyphens? Yeah, it's a flag, idiot. Okay. Okay, so we got team. It makes a model and a factory and a migration. We got project. We got thread. We got message. So I'll say, first we'll commit this. PHP artisan make model MF message, project, team, thread and push. We made all those models. Now go into user tab. Uh, now go write unit tests in test unit for all of the above relationships, all of the needed relationships. And before I give it any extra guidance, let's just kind of see what it does with that. And then I think one piece of pass configuration is we have to apply refresh database to unit. Okay, let's take a look at our unit test. Delete example test. Uh-oh, it wrote them in PHP unit syntax. Dang it. All right, let's take a look and see if anything's missing. User belongs to a team. User has many projects. User has many threads. User has many messages. Okay, message. Message belongs to a user. Message belongs to a thread. Project belongs to a user. Project has many threads. A team has many users. A team has many threads. Okay, hang on. Projects. First of all, those are all PHP unit syntax. Change them all to pest. We're missing projects can belong to a team. Let's just say this. Teams can have projects. Okay, projects can belong to users or teams. Am I missing anything else? Okay, so now if I run a thing like PF team test. What's this? That'll be fixed in a second. Where can I put my face? Project belongs to a user. Belongs to a team. Okay. So one last review. Message belongs to a user. Message belongs to a thread. Message can be created by the system. Project test. A project belongs to a user. A project belongs to a team. Project has many threads. Project belongs to either a user or a team. Team has many users. Team has many threads. Team has many projects. Thread belongs to a user. Thread belongs to a team. Thread belongs to a project. Thread has many messages. User belongs to a team. User has many projects. User has many threads. User has many messages. User can have projects with their team. That seems comprehensive. Okay, let's start a new chat. And let's go one by one. I may actually want all this stuff. Given these files, please go fix these tests. Let's just see if that does it. The message model is missing the relationships. So once we get all this functionality in place, then it's just like we've got all the data models in place to implement our feature. The actions from the system requires thought separately. There we'll be kind of pulling over probably some of the LLM code from other apps where we've implemented this. Maybe we'll do some of that from scratch. I don't know yet. We should think about what other kind of UI we want. UI we need. List of threads. Thread list of messages. List of users. We need a list of users threads. A list of threads messages. A list of users projects. List of teams. Users teams. And then maybe a list of teams projects.
[19:59] Speaker: So we'll build up to that. Tests all fail because you didn't change migrations. Do that now. Don't add new migrations. Change the existing ones. Let's name these components. Thread list, message list, user projects, user teams. We'll also want a team switcher to switch contexts. List of teams projects. We have three passing tests. Message test. What's the other one? PF project test. Project test fails with this. Look in. Boom. And get all those files. Get them all working. The more you keep things simple within patterns that the LLM has been trained on, the more you can trust its output. Well, we're going to need login, logout, of course. These guys had a good, very simple code in Livewire, but we'll extract that to where we need to go. I see a little bit more green. When we do the UI components, we're probably going to want to start differentiating between the core components, the blocks, building blocks that we're maybe hoping to get from our OpenPress integration versus stuff local to our app. Like this, I might just keep this whole components folder for blocks. Move the logo down to the resources views. I'll think about that one. Let's update the thread test to remove the team relationship test as threads are not directly related to teams. I guess it's thinking that threads are related to projects. Need to think about that one. All pass but one. The issue is in the project factory. By default, it's creating a user for each project. Let's modify it to create projects without a user or team by default. Alright, everybody, we have 18 passing unit tests. Very nice. Thread belongs to project and then project belongs to team. Yeah, I guess team shouldn't have raw threads. Maybe? I don't know. Okay, we have passing unit tests. Let's go up to our feature test. So one thing I like to do sometimes is save this. Okay, let's try this. Fixed these. No, you need to look at all relevant files yourself and fix them yourself. Look through codebase with view hierarchy. Adding the missing routes to the API file. What the hell? Oh, it added this migration before the other migration. Delete the migration you made and edit directly. 404s for everything. Move routes from API into web. I think API appends a slash API thing. Well, one of them passes. Only one failed. Fix it and add. Well, something in the feature test is expecting to be able to pull threads for a team, I guess, separate from the individual projects. So we'll just at least put that in the database as an option. Gotta still think through the UI that we want. Just, like, fix it, you know? 34 passing tests! 34 passing tests. That's pretty nice. Let's update our test results.
[39:59] Speaker: So we've got a bunch of unit tests, some feature tests, but do we have any UI here at all? So, okay, we've got a whole bunch of backend functionality working, but I can't really verify that it's working too well because we can't see anything. So I think at slash chat, we will put some of this UI. Or we put it on the homepage if you're logged in. Okay, I think I want to make the homepage show a different view based on whether you're logged in or not. Because we should probably expect that users, like messages and threads will be attached to users. So let's require that you to log in. Email pass, very simple. So let's do this. Look at homepage test and the test results. And maybe the homepage. I don't even have a controller for that. Add a test to homepage test that if the user is logged in, they see dashboard view instead of the unauthed homepage. And implement it and make a basic dashboard view. Okay, and then we will pull in a little bit of very basic auth. Let's take a look at this thing here. Let's write a second one. I'll say, scrape this, look at routes web PHP. Write a basic auth controller for login and logout. Write a log in and log out. And add the routes to routes PHP. Use the functionality from the Mary doc, but in vanilla Laravel, not livewire. Okay. All right, first, let's see what this did. Looks good. Auth check, view dashboard, view homepage. Hey, that works. Do all our tests pass? Yes, they do. Okay, let's get some auth working. Including a basic login page. Let's have it also look at our homepage. Although, was log out already implemented? I think what comes with Laravel only has a post log out, not a get log out. Yeah, post log out. Oh, wait a second. Oops, I might have duplicated some stuff. You. Whoa. What the? 204, what? Huh. Well, the login and logout are working, but whenever I click the button to log in, register, log out, I get a 204 response back and the page doesn't change. It only reflects when I refresh. Can you add appropriate redirects and update tests as needed? Make sure to look through for existing functionality and don't duplicate. Just like made this shit up, but that's really cool. Well, I'm about ready to make a text area where we can do some chats. Uh-oh. Let me try something. It still didn't redirect. Make the changes. I'm realizing that I gave it the Mary article, which implemented login and logout maybe separately from the blade that we put in to begin. I'm guessing it's because... Okay, so I'm not gonna worry about that right now. I'll refactor the auth later. The point is that we are able to log in. I just wanted to get that basic concept in place. Okay, so I actually want this to be a... Somewhere I think I've got... In a previous code base, I kind of like this thing here. Maybe eventually this sidebar. Yeah, let's do that. Look at this on the OpenAgents Inc slash OpenAgents.com repo main branch and make our dashboard look like that. Put the center card in commented out for now. We may move that later. And then what is used for text area, input box. All right, let's see what it does with this. I thought we already had a dashboard view. That's gonna fail because it has already exists. This is a mistake, but it doesn't matter. Okay, well, I hate that focus thing.
[59:59] Speaker: Great, except... Actually, let me just see if I can... Is there a border here? Outline none. Great, except change text to... How can we help? And there's a ring or border around the text area. Light gray and blue when I focus. I want that completely gone. I'm going to move the components and log out to a nav bar. Hell yeah. Perfect. Now, please move the... View components and log out to the top right of the screen. And not as wide. I'm going to throw an autofocus there. Great. Perfect. Just make the button look like this. But preserving the colors you have. That's not perfectly vertically centered right there. Out of curiosity, can I just do a... What? What's ME? Alright, whatever. Doesn't matter. Okay, we got a little form. But submitting it doesn't do anything. Let's go back to this chat. Take another look at this. Right now the submit form doesn't do anything. Write a new feature test called sendMessageTest. It's a good looking form. I want to type in it. Dashboard.blade is getting pretty long. We'll split it into smaller components soon. Handle the case where a thread ID is not provided. Oh nice, like starting a new chat. Good catch. Wow. What's in sendMessageTest? I don't need this. Thread's title. Let's make that nullable. Or start it as a new chat. Remove the project ID constraint. Okay. Let's see if that broke any tests. Uh-oh. Put project ID back, you broke my other tests. You're right, removing the project ID could have broken other parts of your application. Almost at a good stopping point here. Let's see. Broke a bunch of other tests because it's making some assumptions. Let's see what other assumptions you're making. Auth user current project ID. Yeah. Too verbose. You broke other tests. Look at this. You broke other tests and are making too many assumptions. This is an initial home dashboard that may not have a project ID attached. So that needs to be optional. Do not assume user has a project ID set. Handle it if it's present, otherwise no. Fix my tests. Okay, so I think offline I'll do some of the UI for this.
[01:19:59] Speaker: What I'd like to get is a good stopping point for this video would be if I can type a message in the chat and have it add it, like create a thread and a message. And I just wanna see this work in the UI. Let's think if there's anything missing here. So we'll do a nav bar and a sidebar. In the sidebar, we'll put the list of user's threads. In the nav bar, we'll put login, logouts, and the team switcher. Main chat screen, we'll have the message list. We might put in the sidebar, like at the bottom, the current project, or at the top. This might be in like a settings dashboard kind of thing. Like a team page. Okay, I'll just think about that. All right, let's see what this did. First, can I see stuff there? I can. Okay, how are my tests doing? Yeah. Fix this. Is that the only problem? Yeah, I'll probably try to pull over some of this UI. This is using Alpine, which we may or may not use. Update the threads table migration to allow for null user ID. I don't know if I want that. Better, we already had those auth tests failing. Auth, auth. Okay, everything but auth passes, that's good. I don't know what this does. Oh, let's restart our database. I'm going to go here. I'm going to register. How did my register go? Did you remove register routes from here? Or was that another agent? Okay. Don't touch it. I could go to the Git history, but I'll just do this here. Oh, it redirected me. Doesn't this feel good? I gotta make it submit on enter. Okay, so what happens when I do that? Let's connect to our table plus. We have a user. We have a thread called testing. And we have a message. Hey, that's not bad. Okay, so we're saving a message. Let's do one more thing. I just want to see like a little bit of a message list here. Thanks, forget about that. I did it. I added it back. So let's see. So I first want to extract this into different components because we're going to edit this and I just don't want to keep waiting for that. So let's do this. Look at boom. Extract that into as many smaller components as you can, putting them in resources, views, dashboard. Terms, privacy. That might be a little excessive. We'll see. And then I just want to see a little list of messages. Cool. Just make sure it all still works. Yep. Okay. Now what do I want to do? Okay. Let's update test results. So I wanted to be able to pass the user's messages to this component just for now. So I'm going to say look at boom and test results. Write a new dashboard controller that the home route will use, which also passes to the dashboard view a list of all the user's messages. Ooh. To complete this implementation, you should update the dashboard view to display the list of messages. Here's an example. Oh, you're already doing it. You have already split this up. Let's go into main content. Let's edit main content. I love open agents. That's a good stopping point here. See you soon.