Transcription: OpenAgents Episode 006 - Implementing Agent Data Models via TDD

June 9, 2026 ยท View on GitHub

Source: https://twitter.com/OpenAgentsInc/status/1722287956419871177 Wiki source: https://raw.githubusercontent.com/wiki/OpenAgentsInc/openagents/Video-Series.md Media title: OpenAgents - Episode 006: Implementing Agent Data Models via TDD We learn about tes... Upload date: 20231108 Transcription model: gpt-4o-transcribe-diarize Generated at: 2026-06-01T01:02:28Z

Machine-generated transcript. Review speaker labels and wording before using this as quote-grade source material.

[00:01] Christopher David: We have a beautiful data model and the relationships to power the first version of our product.

[00:09] Christopher David: We're going to code them up via test-driven development.

[00:12] Christopher David: Laravel makes testing super easy using PHP units and we're going to use this newer framework.

[00:20] Christopher David: It's like a superset on top of PHP unit called Pest.

[00:25] Christopher David: So just to give you an example,

[00:26] Christopher David: if I run the tests now, and I'm going to run the pest command,

[00:30] Christopher David: which is just going to run the tests, all of the tests via PHP unit,

[00:33] Christopher David: our application comes with a bunch of tests already.

[00:38] Christopher David: And we've got, for example, an example unit test.

[00:43] Christopher David: And this is, oh yeah, that is using the pest.

[00:49] Christopher David: framework you used to start it off with the more verbose php unit syntax but now it just creates you the past because we did that in our inertia setup uh expect true to be true there's a demo of a test there a unit test and then we've got an example feature test returns a successful response go to the home route make sure that it's a say it succeeds and then when we did the breeze scaffolding we got a whole bunch of feature tests in off

[01:19] Christopher David: so test that you can the reset password link screen can be rendered blah blah blah and so before I started recording when I had all of this stuff commented out whenever the test it all fails

[01:35] Christopher David: And so this is great to ensure that functionality that you expect to be true when you deploy,

[01:42] Christopher David: you run this and you can know, assuming that you've got thorough test coverage, like you've got the relevant functionality tested like this,

[01:50] Christopher David: that you're not pushing broken code into production.

[01:55] Christopher David: So this is great.

[01:58] Christopher David: And what we're going to do soon is create unit tests for all of our model relationships.

[02:04] Christopher David: But first, let's get familiar with PaaS.

[02:08] Christopher David: Gosh,

[02:08] Christopher David: you know,

[02:08] Christopher David: in the previous video,

[02:10] Christopher David: I was thinking that I would have to install PaaS,

[02:16] Christopher David: but PaaS is already installed because we selected that when we installed it.

[02:20] Christopher David: So that's easy.

[02:23] Christopher David: Let's write our first test.

[02:27] Christopher David: Let's do let's

[02:32] Christopher David: build a test for user has many agents

[02:37] Christopher David: I guess we'll put that in the user make it let's make a user test user test dot PHP

[02:45] Christopher David: so I want to test and

[02:50] Christopher David: we'll have copilot help us out here

[02:54] Christopher David: You can also make it say it.

[02:56] Christopher David: So like it, if you're referring to a user,

[02:58] Christopher David: it has many agents.

[03:07] Christopher David: So let's see if Copilot knows what to do.

[03:14] Christopher David: Well,

[03:14] Christopher David: let's create a user.

[03:15] Christopher David: So user equals, yeah, that's one way of doing it.

[03:22] Christopher David: Create a user and then assert that.

[03:32] Christopher David: That's a good start.

[03:33] Christopher David: This is going to assert that user agents is a collection.

[03:41] Christopher David: I'm going to run pf user test.

[03:47] Christopher David: So that fails properly.

[03:49] Christopher David: Okay,

[03:49] Christopher David: so pf.

[03:52] Christopher David: Let me show you my, so

[03:57] Christopher David: I've got this aliased.

[04:00] Christopher David: Alias P is vendor bin past.

[04:03] Christopher David: Alias PF is vendor bin past filter.

[04:08] Christopher David: So instead of that, you could run vendor bin past filter user test.

[04:18] Christopher David: And it'll run that.

[04:20] Christopher David: Okay.

[04:23] Christopher David: So we write a test that we expect will pass once the functionality is implemented.

[04:35] Christopher David: A facade root has not been set.

[04:41] Christopher David: What does that mean?

[04:46] Christopher David: Here we do the old thing called Google the error.

[04:56] Christopher David: Facade root has not been set. What the heck does that mean?

[05:00] Christopher David: Let's make sure that we got the application running fine.

[05:29] Christopher David: I'm guessing that our pest config is missing something out of the box.

[05:35] Christopher David: So I'm going to jump over to our previous code base and

[05:44] Christopher David: just take a look at this is where I installed pest manually.

[05:48] Christopher David: OK,

[05:48] Christopher David: yeah, we're not using I guess it needs to import from test case.

[05:55] Christopher David: not just for feature tests but for unit tests also let's see if that makes a difference it did okay so

[06:06] Christopher David: i'm just going to change the syntax to be prettier here i guess there's a default assumption that you're not going to be using database refreshing in the test case class in your unit test but i am going to be doing that okay so

[06:24] Christopher David: Let's commit that. Apply test case.

[06:28] Christopher David: Refresh DB to unit tests.

[06:34] Christopher David: Commit this as re-enable auth routes.

[06:40] Christopher David: Okay, we have a failing test with the error that we expect.

[06:44] Christopher David: User agents is null.

[06:46] Christopher David: It doesn't know what that is.

[06:51] Christopher David: So we want agents.

[06:57] Christopher David: So I'm going to say has many agents,

[07:00] Christopher David: public

[07:02] Christopher David: function agents,

[07:03] Christopher David: this has many app models agent.

[07:05] Christopher David: Now, of course, we haven't defined has many agents or haven't defined that model yet.

[07:10] Christopher David: But let's see what the new error is.

[07:12] Christopher David: Class app models agent not found.

[07:15] Christopher David: Great.

[07:16] Christopher David: We just go error by error.

[07:19] Christopher David: Then we do the command for creating a new model,

[07:22] Christopher David: which is PHP Artisan.

[07:25] Christopher David: Make model M for the database migration at the same time agent

[07:32] Christopher David: Alright that created two things our model file very basic and then database migration right

[07:42] Christopher David: there

[07:45] Christopher David: So if I do php artisan migrate and if I look in my local table

[07:52] Christopher David: I now have a table for agents with just ID created and we're going to rebuild that as we kind of drive out the columns that each table needs.

[08:05] Christopher David: Let's check in on our test.

[08:08] Christopher David: Undefined column.

[08:09] Christopher David: Column agents.userID does not exist.

[08:13] Christopher David: Cool.

[08:14] Christopher David: We're going to do here a foren ID userID.

[08:20] Christopher David: Let's try that.

[08:22] Christopher David: Thank you, Copilot.

[08:23] Christopher David: User test.

[08:24] Christopher David: It has many agents. Ladies and gentlemen, we have our first passing test.

[08:30] Christopher David: Look how easy that was.

[08:32] Christopher David: And what we did was create a relationship between the user model and the agent model.

[08:41] Christopher David: So what I'm going to do is make a little list for myself here.

[08:48] Christopher David: And after I've written the test and the functionality for it,

[08:55] Christopher David: new test.

[08:56] Christopher David: User has many agents.

[09:00] Christopher David: And let's write that as user has many agents passes.

[09:07] Christopher David: That was easy.

[09:09] Christopher David: Now,

[09:09] Christopher David: what's the next one?

[09:10] Christopher David: Okay, so user and agent have many conversations.

[09:15] Christopher David: Start with user.

[09:18] Christopher David: Let's go back to our user test.

[09:23] Christopher David: Oh, and there's other things that we could do here.

[09:25] Christopher David: Right now we're just testing that it's a collection,

[09:27] Christopher David: but let's say assert it's an

[09:34] Christopher David: instance of an agent.

[09:40] Christopher David: Does that still pass?

[09:44] Christopher David: Okay,

[09:45] Christopher David: so this one doesn't pass because it's looking for a first.

[09:51] Christopher David: So basically we've asserted that the user agent is a collection,

[09:55] Christopher David: but if the collection has zero,

[09:57] Christopher David: then we're not also testing that you can create one.

[10:04] Christopher David: But that maybe is worth a separate test. What do I want to do here?

[10:12] Christopher David: I guess we could do, just to make this a little bit more thorough to demonstrate factors,

[10:18] Christopher David: let's also create a demo agent.

[10:22] Christopher David: And we're going to set the user ID of the agent to

[10:32] Christopher David: be that of the user that we just created.

[10:39] Christopher David: Okay.

[10:39] Christopher David: Now in this case, it fails because it doesn't find a factory for agents.

[10:43] Christopher David: So factory is just something that kind of creates as a demo one using kind of faker data.

[10:49] Christopher David: As you can see, the user factory defines that here.

[10:52] Christopher David: So we're going to just do some copy pasta here.

[10:55] Christopher David: I'm going to make agent factory.

[10:59] Christopher David: Agent factory.

[11:02] Christopher David: While also dreaming about when we're going to have agents doing this kind of copy pasta for us.

[11:08] Christopher David: And let's remove this is

[11:13] Christopher David: there anything else that we need for this factory here?

[11:16] Christopher David: Oh look it succeeded

[11:20] Christopher David: Now that would probably fail I think if I were to comment out the definition of the user ID

[11:27] Christopher David: That's as we would expect and that errors fine

[11:30] Christopher David: Okay

[11:32] Christopher David: Let's clean this up a little bit.

[11:33] Christopher David: I like

[11:36] Christopher David: Importing the stuff up here,

[11:39] Christopher David: alphabetizing it,

[11:45] Christopher David: make it a little tighter.

[11:53] Christopher David: Okay.

[12:04] Christopher David: And set up.

[12:07] Christopher David: Agent Factory.

[12:09] Christopher David: Okay.

[12:12] Christopher David: Next,

[12:13] Christopher David: a user and agent have many conversations.

[12:19] Christopher David: It has many conversations.

[12:29] Christopher David: Look at that.

[12:30] Christopher David: Thank you, Copilot.

[12:33] Christopher David: Except I don't want this to be Asian. I want this to be conversation.

[12:38] Christopher David: I want this to be conversation.

[12:43] Christopher David: It's all pretty much similar.

[12:49] Christopher David: Okay,

[12:49] Christopher David: class conversation not found.

[12:51] Christopher David: Well,

[12:52] Christopher David: I know it's going to look like this.

[13:01] Christopher David: All right, we're going to repeat that.

[13:02] Christopher David: Make model M, conversation.

[13:09] Christopher David: See our test fails.

[13:11] Christopher David: Conversation factory is not found. Let's just duplicate, oops that was the wrong thing.

[13:17] Christopher David: Duplicate the conversation, the agent factory to be conversation factory.

[13:25] Christopher David: And later when we want more elegant fake data created when we do conversations.

[13:32] Christopher David: Back to this.

[13:34] Christopher David: Okay,

[13:35] Christopher David: column user ID of relation conversations does not exist.

[13:44] Christopher David: We will copy this for an ID.

[13:56] Christopher David: Fail asserting that null is an instance of class. That's because we haven't defined it on the model.

[14:04] Christopher David: conversations and

[14:09] Christopher David: it passes user

[14:15] Christopher David: has many conversations now

[14:21] Christopher David: do you want the conversations to belong to agents too

[14:34] Christopher David: So that would go under an agent test.

[14:41] Christopher David: We can actually reuse this entire thing,

[14:50] Christopher David: agent test,

[14:55] Christopher David: and it in this case being agent.

[15:07] Christopher David: agents now

[15:12] Christopher David: that will probably fail because we're not passing a default user ID so we'll probably want to do this agents is yeah and then for the conversation

[15:35] Christopher David: this agent

[15:38] Christopher David: agents.

[15:41] Christopher David: Without even thinking about it let's just see what tests I get here.

[15:44] Christopher David: PfAgent test.

[15:46] Christopher David: Okay failed asserting that agent conversation is a class of collection. So agent let's just actually copy pasta the code directly from here has many conversations over to the agent model.

[16:07] Christopher David: undefined column conversations.agent ID does not exist

[16:21] Christopher David: we may decide later that it's actually not appropriate to have conversations attached also to an agent some of this might be duplicative but I'm not going to worry about that for now okay so not null violation no value in column

[16:34] Christopher David: Agent ID of relation conversations validates not null.

[16:38] Christopher David: So what we're saying now is that in the agent test,

[16:44] Christopher David: when we create a conversation,

[16:48] Christopher David: it's now expecting that to be non-null.

[16:53] Christopher David: We could set it as null,

[16:54] Christopher David: but I think for now we'll just pass in.

[16:59] Christopher David: agent IB and see what that does booyah agent now has many conversations now do all of our unit tests pass can I filter by unit looks like I can now look this is why you always run your your tests every time you make code that changes you make changes because our agent test passes but now we broke our user test so we go back to our user test

[17:27] Christopher David: and say we also need to assign the conversation to an agent.

[17:31] Christopher David: But what if we don't want to?

[17:34] Christopher David: What if we want to say, you know,

[17:36] Christopher David: I don't actually think that that should be necessary.

[17:39] Christopher David: I think we can make this nullable.

[17:41] Christopher David: Let's try it.

[17:48] Christopher David: Violates not null constraint.

[17:52] Christopher David: I don't think it can be both constrained and nullable.

[17:57] Christopher David: Okay, our test pass.

[18:00] Christopher David: This might be some kind of bad,

[18:04] Christopher David: I don't know, but we're only going to be focusing on how beautiful our green tests are.

[18:10] Christopher David: Ooh,

[18:10] Christopher David: our tests are green.

[18:13] Christopher David: We'll maybe we'll run into that, this being a problem of not being constrained later,

[18:18] Christopher David: but that's not something we need to solve right now.

[18:21] Christopher David: Okay.

[18:22] Christopher David: So, what do we do?

[18:24] Christopher David: User and agent have many conversations.

[18:27] Christopher David: Boom.

[18:35] Christopher David: User has many files.

[18:39] Christopher David: Okay, for things that are just copy-paste, I'm going to skip past those in this video. I'll do those offline.

[18:47] Christopher David: Conversation has many messages.

[18:48] Christopher David: That's the same.

[18:49] Christopher David: Conversation may have many files. That's an optional.

[18:52] Christopher David: Has many.

[18:53] Christopher David: Agent has many tasks.

[18:54] Christopher David: Task has many steps.

[18:56] Christopher David: Task has one output.

[18:58] Christopher David: Step has one output. Step may have many artifacts.

[19:03] Christopher David: So you've seen that I did these two in five to eight minutes or so.

[19:09] Christopher David: And so I'm just going to offline take half an hour and go.

[19:14] Christopher David: get all of these things implemented.

[19:18] Christopher David: Once they're implemented, then

[19:23] Christopher David: we can very easily create API endpoints that manipulate these models.

[19:30] Christopher David: So we'll do that in the next video.