HomeVideos

Building durable Agents with Workflow DevKit & AI SDK - Peter Wielander, Vercel

Now Playing

Building durable Agents with Workflow DevKit & AI SDK - Peter Wielander, Vercel

Transcript

1577 segments

0:20

Thank you all for coming. Hello. Hello.

0:25

>> Got you.

0:28

Uh, I don't know about you, but um, my

0:31

ride agents, I like focusing on the

0:36

capabilities and the features, and I

0:38

like not thinking about um, all of the

0:41

extra effort that goes into getting

0:43

something that works locally into

0:44

production. And something that's very

0:47

useful for that is uh, a workflow

0:50

pattern. And that's why we developed the

0:52

workflow def kit which is what we're

0:54

talking about today. Presumably if

0:56

you're here you've had similar issues.

0:59

Um and today uh we are going to um turn

1:04

a agent uh coding agent um into a

1:08

workflow supported coding agent

1:10

throughout this session. So

1:14

this slide. So we um have a open- source

1:18

example um ready to go. Uh this is on

1:21

the versel/examples

1:23

repository. Uh so you can clone that and

1:27

check out the VIP coding platform app

1:29

insight. Uh we're going to be using this

1:31

app um for today's demo.

1:35

Um and after we're done we get first

1:39

class observability built in and also

1:42

durability reliability. uh we get a lot

1:44

of extra features like resumability

1:47

um and

1:49

draft kit makes it very easy to add

1:50

human in loop workflows and similar uh

1:54

things.

1:56

So if you think about our uh general

1:59

agent loop um that we've all seen

2:01

before, we mostly have calls back and

2:05

forth from another LAM um to our to

2:08

calls and our backend uh code, right?

2:11

Which would include MCP servers, human

2:13

approval, any kind of async tasks.

2:17

And uh the usual way to go about this is

2:20

to uh wire up some cues um and a

2:24

database especially if you are doing

2:26

longunning agents right that might run

2:29

for hours um and you want to scale and

2:31

you're running on serverless for example

2:33

uh you want something some kind of

2:35

reliability layout in between which

2:37

usually is filled by cues um and then

2:40

you'll also need to add a lot of error

2:41

and retry code you'll need to store all

2:44

the messages that people are sending and

2:46

also between states and you probably

2:49

also need to add some kind of

2:51

observability layer in between. All of

2:54

those things we are going to do today uh

2:56

using only a single library which is the

2:59

workflow development kit. Um it's open

3:02

source um and it runs with any of your

3:06

TypeScript um front ends or backends and

3:10

can also run on any cloud. Uh we're

3:13

going to be deploying to Brazil today,

3:15

but this could just as easily run or any

3:18

of your cloud stacks um orbase or any of

3:22

your custom stacks.

3:26

Um all right, so who here has heard of

3:30

the workflow pattern or has used a

3:31

workflow library before? Show of hands.

3:35

All right, that's less than half. Um I'm

3:38

going to quickly explain what a workflow

3:39

pattern is um to uh make it clear what

3:42

we're doing and then in about 2 minutes

3:44

we're going to go into the code. So um a

3:48

workflow

3:49

pattern is essentially a sort of

3:51

orchestration layer um that separates

3:53

your code into steps that can run in

3:55

isolation and can be retrieded um and

3:58

have their uh data persisted and a

4:03

orchestration layer um that we call a

4:05

workflow within platforms have different

4:07

names for that. And in our case here, um

4:11

the the workflow parts would be whatever

4:13

the loop is that calls um the reason the

4:17

LM calls and then goes back to the tool

4:18

calls and then back to the LM calls. And

4:21

the steps would be our actual tool calls

4:24

and our LM calls. Um

4:28

right, so looking at the agenda for

4:30

today, um we're going to be jumping

4:32

jumping into the code. We're going to

4:34

add workflow development kit which is

4:35

going to be quite fast and then we have

4:37

a lot of time to talk about uh cool

4:40

additional features that it adds like

4:42

resumable streams out of the box um how

4:45

to suspend and resume at any point um

4:47

and how to add web hooks for human in

4:50

the loop uh processes. At the end

4:52

there's going to be ample time for Q&A

4:55

but there is a reason that you're here

4:56

in the workshop and not looking at this

4:59

online which is that you can ask

5:00

questions. Please do so at any point. Uh

5:03

feel free to raise your hand or just

5:05

shout out the question. Um and we'll get

5:08

rid of

5:10

all right so as I said uh we're working

5:14

off the baselample repository and we're

5:17

going to be working off of the conface

5:20

branch. Uh why this branch? I stripped a

5:24

bunch of the access code on the example

5:26

to make sure that we can focus on the

5:28

most important parts. And every

5:30

checkpoint from this workshop will have

5:32

its own branch. So uh if you're not

5:35

coding along directly, you can also

5:38

check out the steps step by step and

5:40

then check the diffs and see what

5:42

changed between.

5:44

All right. So

5:47

um I have already run uh npm dev locally

5:52

on this uh um platform just to show you

5:54

what it looks like. I'm going to run a

5:56

simple query. Um so this is a uh coding

6:00

agent, right? It's like a code editor

6:02

but without the code editing and it can

6:05

take a prompt, generate some files and

6:08

it'll eventually show you a iframe with

6:11

the finished app that is deployed. Um,

6:14

so it's it's mostly UI with a few simple

6:16

tool calls um that we'll look at in a

6:18

second. And the file system and output

6:21

uh runs over the cell sandbox, but you

6:24

could just as easily run this locally.

6:27

Uh, looking at the code, I'm going to go

6:31

and check out our actual branch.

6:36

Looking at the code, uh, we have one

6:39

endpoint that accepts our chat messages,

6:41

right? Then it does some some regular

6:44

sort of model ID checking with us to see

6:46

whether the model is supported. And in

6:48

the end it's going to simply create an

6:51

agent. Oh yes.

6:53

>> What was that branch one more time?

6:55

>> The branch was

6:57

conf.

7:01

Yeah. And you can see we'll we'll move

7:03

on to these com/2- etc. Uh just look for

7:06

the numbers and you'll find all the

7:07

checkpoints.

7:10

Um yes. So our main endpoint just

7:13

accepts some messages and calls the AI

7:17

SDK agent which is essentially the same

7:21

thing as a stream text call. Um we'll

7:23

pass some tools and internally it'll

7:25

just loop for stream text to call stream

7:28

text call. uh and then it'll uh stream

7:33

the all of the chunks generated back to

7:36

the client in a format that is easy for

7:39

the client to understand. This is all

7:41

sort of AISDK regular code um that you

7:44

could replace with a different library

7:46

if you want. Um that is mostly there to

7:49

support the UI. Um but again all of the

7:51

actual agent stuff is very simple and

7:53

happens here. So

7:56

uh oh let's also take a look at the

7:59

tools that we have. Uh we have four

8:01

tools uh create sandbox get sandbox URL.

8:05

These are very simple. They just wrap uh

8:07

bell sandbox.create and get URL and

8:11

similar with run command essentially

8:13

reps uh sandbox.r run command and

8:16

generate files um will generate uh a

8:20

file from a simple prompt. And we're

8:22

going to take a look at one of these

8:23

root calls as an example. Uh we have a

8:26

we have a prompt that looks somewhat

8:28

like, you know, a markdown file. Sort of

8:30

what to do, what not to do. Um and

8:34

my hotkeys are not working. And

8:40

back to the tool call. We also have an

8:42

input schema that's a Z schema um for

8:45

what BI is supposed to pass. This is all

8:47

very standard. and then an execute run

8:50

which wraps sandbox one command with

8:54

some error handling.

8:56

So that's essentially our entire agent

8:59

code setup and then in the front end we

9:01

just call use chat from AI SDK to

9:03

consume the stream and display uh things

9:06

in the UI. So uh let's get started

9:10

adding workflow to this. Um any

9:13

questions before I get started?

9:17

Cool. All right. Uh, so step one is

9:21

we're going to run npm install for

9:24

workflow and add workflow

9:28

which will give us the latest version.

9:30

Uh, workflow is the main library and add

9:33

workflow are some helpers for uh uh some

9:38

some rappers for

9:40

that work well with the workflow

9:42

development kit.

9:44

So now that we have this installed, uh

9:47

we are running a Nex.js app here. So

9:49

we're going to uh extend the compiler to

9:54

uh compiler workflow code by doing use

9:56

workflow or with workflow. Um which we

10:01

can import from

10:05

workflow next

10:10

and that'll set up next.js. Yes.

10:13

>> Verifying question. You are in the

10:16

example applied coding directory.

10:19

>> Yes.

10:23

>> So adding this will let the compiler

10:25

know to also compile our web um

10:28

separately which we'll get into more in

10:30

a second. And then for convenience, we

10:33

can also add a TypeScript plugin to our

10:36

TS config um same package and that'll

10:39

give us some better autocomp completion

10:41

for our workflow code.

10:44

And so we talked about uh a workflow

10:48

being

10:49

um having an orchestration layer and

10:51

having a number of steps. Uh what we're

10:54

going to do first is we're going to

10:56

write the orchestration layer. Um, in

10:59

our case, that is essentially just the

11:00

agent, right? Does the loop that calls

11:03

steps um back and forth. We're going to

11:07

add a new file. Uh, you can call it

11:10

whatever you want. And we're going to

11:12

take our

11:14

agent call and move it over there. And

11:18

I'm going to call this our uh code

11:22

workflow,

11:25

which is going to be all of our workflow

11:29

code.

11:32

And then I'm going to go and auto

11:35

complete a bunch of imports.

11:42

Thank you, AI. So we're just passing

11:45

most of the uh arguments that we would

11:48

otherwise get from here over there. And

11:53

this completes the refactor. Essentially

11:55

having done nothing but pull out some of

11:57

the workflow code into our file. So this

12:00

is where it gets interesting. Um, now

12:02

that this is a code, this is a separate

12:04

function, we can use the use workflow

12:06

directive

12:08

which will mark this for our compiler as

12:12

a workflow function.

12:14

So what this does is under the hood,

12:16

yes. Oh, sorry.

12:20

uh under the hood it um compiles all of

12:24

the code related to the function into a

12:26

separate bundle and it ensures that

12:28

there is no imports to anything that

12:29

would have side effects because the

12:32

workflow orchestration layer needs to be

12:33

deterministic. So it can be rerun um in

12:36

a in a uh deterministic fashion and

12:41

there's no worries about state uh

12:43

pollution.

12:45

So now that we have this um we would

12:48

need to now mark our LLM calls as steps

12:54

and because the calls are happening

12:56

inside the agent um this is a little bit

12:58

harder to do here and so we uh ended up

13:03

writing a

13:06

durable agent class which is essentially

13:09

the same thing as agent with a use step

13:13

marker in the actual LM calls that it

13:16

does under the hood.

13:19

So, now that we have this set up, we're

13:23

going to

13:25

await the actual streaming and let's see

13:29

if there's anything

13:32

we need to do.

13:35

Um, checking for errors. Oh, yes, we

13:38

need a stream to write to. So,

13:40

previously we could just write to the

13:42

stream that the API handler gave us. Uh,

13:45

now we're going to have to create a new

13:49

stream to write to. Um, we export a get

13:53

writable function from workflow which is

13:57

which gets a stream implicitly

13:59

associated with the workflow to write

14:00

to. And we're going to get get into that

14:02

a little bit more in a second. But for

14:04

now, we'll just pass that to our agent.

14:09

And we're going to see if this is right

14:13

type.

14:15

Um, presumably

14:17

not.

14:20

Um and then finally

14:23

back in our actual workflow

14:27

we need to call our workflow in a way

14:29

that the uh framework understands which

14:32

for us is a call to start

14:37

with the arguments being passed

14:39

separately which is essentially telling

14:41

it to start a new workflow

14:45

on this on this function and start can

14:47

be imported from workflow/ API Okay,

14:51

so now we essentially have uh the

14:55

workflow fully hooked up and a lot of

14:57

this was just pulling out some of the

14:59

codes and adding a directive.

15:06

Yeah.

15:08

Um

15:10

has volunteered to help anyone who's

15:12

like following along and has some

15:14

debugging questions. Um just reach out.

15:17

>> I'm on the team as well. So let me know

15:19

if you guys are following one.

15:21

>> I'll be around to help.

15:24

>> And finally,

15:25

this start call returns a run instance

15:28

um that has the stream that just um end

15:31

up writing to that we can return to the

15:33

UI. So this completes our workflow um

15:37

definition. And now uh we also said that

15:40

we would need to mark things as steps.

15:42

The durable agent class already marked

15:45

the LLM calls as steps. But our tools

15:48

right now are not marked as steps.

15:50

Thankfully, this is very easy. Uh in the

15:54

execute function for each of these

15:55

tools, you can just write use step and

15:58

that will let the compiler know that

16:00

this is a separate chunk to uh of code

16:03

to uh execute in a separate instance.

16:07

Right? If this is deployed to

16:08

production, this would run in a separate

16:10

serless instance and the inputs and

16:12

outputs would be cached if it already

16:14

ran and it would be retrieded if it

16:16

failed. So I'm going to go and

16:20

go through the other tool calls and also

16:23

add use step to these. Thankfully we

16:26

only have four of them.

16:30

And that should complete our

16:33

transformation.

16:35

So now we can go and run the mpm dev.

16:41

See if this works as expected.

16:44

We're going to reload our page.

16:51

And it seems like nothing changed. Let

16:53

us actually run a query.

16:57

And we can see that it's still streaming

16:59

as expected. So uh for us developing

17:03

locally right all we had to do is pull

17:05

out a function um and then add some

17:07

directives. But now if I deploy this um

17:11

to any adapter again was or an AWS

17:14

adapter or maybe you have your own um

17:18

this will run uh in isolation with

17:20

durability and all of those good things.

17:23

And something that's really nice for

17:24

local development also is that if I go

17:27

and

17:30

if I go and I'm going to go into the

17:32

same folder here and I'm going to run

17:34

npx workflow web which is this cli call

17:39

to start a local web UI to inspect our

17:41

runs. Um and you can see that our run is

17:44

currently still running. Um and every

17:47

step everything that is marked as a step

17:49

will have a uh span here and you can

17:52

inspect the inputs the outputs and any

17:55

associated event. And we can see that

17:57

our workflow just completed I think and

18:02

yeah this gets built in. Yes.

18:03

>> And just for clarification every time

18:05

you're prompting your vibe coder that is

18:07

is one instance of the workflow that

18:08

runs to completion. So then so each one

18:12

is Yeah. It's

18:13

>> exactly Yeah. And you could model this

18:14

uh in any way you want. Um you can also

18:17

model your entire like an entire user uh

18:20

sort of uh session as one workflow and

18:24

uh have the workflow sort of do a loop

18:27

wait for the next query um and then

18:30

again you know we can run code for weeks

18:34

if we need to essentially um

18:37

and I'm going to go into uh some tools

18:40

for that in a second.

18:42

So now that we have this uh set up uh

18:46

you can see that um on the right side we

18:48

do not get any sort of helpful uh

18:51

feedback. But um if I visit this link

18:55

and see that our app

18:58

has likely been created correctly

19:02

um or or it failed because of some

19:06

errors

19:08

and

19:10

either way we're not getting any output

19:11

on the right side. So uh the reason this

19:13

is happening is that we are streaming um

19:17

the agent output to the client but our

19:22

tools aren't actually doing any stream

19:23

calls right now. So what we could do is

19:27

similarly in our tool calls uh we could

19:30

get the writable

19:34

um which would which will get the same

19:36

writable instance as any other uh as the

19:40

workflow itself. Um there is an infinite

19:42

amount of streams you can you can create

19:44

and consume in a workflow. Um and you

19:46

can also like you can tag them with a

19:48

certain name and then fetch them from

19:50

there. Um but this will get the default

19:52

instance.

19:54

And once we have a writable we can

19:56

actually connect to the writable

20:01

by getting the writer. And now we can

20:03

write any kind of information um to the

20:08

to the iPhone to be consumed. I think we

20:10

want something like data create sandbox

20:13

I think is what I hooked up in the UI

20:16

and then

20:18

we'll call ID

20:21

we want the sandbox ID do it here. So

20:24

this is me just writing a data packet

20:27

that our UI knows how to consume. So now

20:31

that I did this and I if I reload the

20:33

app and start this again, we'll see that

20:36

at least the sandbox create call

20:41

presumably gets filled in correctly at

20:43

the start.

20:47

>> Yeah,

20:48

>> you said that there are stream that you

20:52

can create and

20:55

what do you mean by that?

20:57

>> Right. Yes. So um a stream

21:03

the workflow sort of the adapter they

21:05

use for workflows in local development

21:07

right this would just just be a file in

21:09

production this might be a reddus

21:10

instance

21:11

>> um supports the workflow calling it to

21:14

create a new stream for example in

21:15

reddus right and then passing that

21:17

stream back and so anytime you call get

21:20

writable it'll create a stream for

21:23

example again in radius with the ID of

21:25

that workflow and it'll pass that So any

21:27

step can attach to that and any client

21:29

can attach to that

21:31

>> and in local uh host this would be

21:34

written to a file and read from a file.

21:38

>> Sorry you're setting up right now.

21:44

>> Right. So pre previously we had a a API

21:47

handler that took some messages called

21:50

the agent and then streamed back

21:52

messages from that API handler. Now we

21:54

have an API handler that calls it starts

21:57

a workflow and it'll pass back the

22:00

stream that this workflow creates. Um,

22:04

what this allows us to do also I think

22:06

that was not working correctly. I'm

22:07

going to restart the server just to see

22:09

if that's the case. Um,

22:11

>> anything else so far getting this set up

22:14

to where where needs any help with

22:18

getting set up?

22:20

>> Seems good. Um good point you made uh

22:24

something this allows us to do is that

22:26

the stream is not bound to the API

22:28

handler. This means that at any point we

22:31

can resume this stream. If you lose

22:33

connection to your API handler and then

22:35

the user reconnects this stream still

22:38

exists and we could reconnect to the

22:39

stream to resume the session. This is

22:42

also part of the durability aspect where

22:44

everything you do in a workflow you can

22:46

resume at any point.

22:49

I'm going to restart this query and hope

22:52

that it works this time. Yeah. So, now

22:54

that I hooked up this data packet, you

22:56

can see this special UI handling for

22:57

creating a sandbox uh works. But even

23:00

after it's done, it's not showing up

23:02

that it's done. This is because we're

23:04

only writing the initial loading state

23:06

packet. So, I could go through all of

23:08

our tools and I could add more packets

23:09

and just, you know, make the UI richer.

23:12

Um, but I'm going to go and check out a

23:15

different branch which is the uh conf-

23:19

sleep branch. Uh, just the next step uh,

23:21

which already has these

23:24

actually I'll go for the workflow one.

23:26

Sorry, conf /2-workflow

23:28

which already has all of these writer.

23:30

Calls populated. There's no difference

23:32

otherwise. Um, so now that all of our

23:34

tools have these right calls, the stream

23:36

would again presumably look the same as

23:39

it did when we started out in this app.

23:42

Um, all right. So, now that we have

23:46

streams working again, everything is

23:48

working as expected and we have more

23:49

observability and we can deploy this

23:51

with durability. Um, I talked about

23:54

resumable streams before. We're going to

23:57

see if we can get this stream to resume

23:59

so we have durable sessions.

24:02

So, the only thing we need to do to uh

24:05

make that work is to go to our API

24:08

endpoint.

24:10

Um, and what where we get the run

24:13

instance, we're also going to return

24:18

the workflow ID

24:23

as a as additional additional

24:25

information. So I can I can return run.r

24:28

run ID for example. This is just again

24:30

any way you do this is fine. Um, I'm

24:32

adding it as a header here because we're

24:34

already returning a stream. But anyway

24:37

you pass the ID to the UI um is

24:39

something that the UI can then use to

24:41

resume the stream from.

24:43

So what we do from here is uh the UI

24:46

should be able to decide whether to

24:48

whether it has a run ID and whether it

24:49

should resume a stream. So we're going

24:51

to go and create a new endpoint. Um

24:55

let's call it

24:59

ID for type slashexisting ID. Then we're

25:03

going to make a folder stream and we're

25:07

going to add a route handler. So this is

25:09

just next.js uh configuration for adding

25:12

an API route at slash chat/ ID/ stream

25:17

and we're going to

25:20

auto complete with AI.

25:23

Um what we're essentially doing is uh we

25:27

get the ID from the params and then all

25:30

we're going to do is call get run in the

25:32

workflow API which gets a uh the run

25:36

instance and then we can

25:39

return the same stream

25:42

that we return in the other endpoint

25:44

just without calling the actual agent um

25:46

only only doing the stream and

25:50

>> this whole project

25:51

>> I think that should be good. Um, we're

25:55

also taking our start index which is

25:57

very helpful from the AI. We can get a

26:00

readable stream um, from a certain start

26:03

point. I think this is why it's auto

26:04

computed. Um, so if you're trying to

26:06

resume a stream like midway, you can

26:08

pass a, you know, which chunk you were

26:10

on when you initially left off. So now

26:14

that this is done, I'm going to comment

26:15

out these things we don't currently

26:17

need.

26:19

um we need the UI to support

26:23

this uh conditional of whether to resume

26:26

or whether to start a new chat. So I'm

26:28

going to go to our chat front end and

26:31

I'm going to go pull in some code from a

26:33

different branch um for simplicity which

26:36

is the it's on the four-streams branch

26:39

which I'm going to

26:42

just show for

26:44

completion. um we do a use chat call

26:48

already in the UI to consume the stream

26:50

and we all we added now is a transport

26:53

layer which is this big block here that

26:56

has some middleware

26:58

for the stream that says that if I'm

27:00

trying to start this call uh I'm going

27:02

to check first whether we have an

27:04

existing run ID and if so I'm instead

27:06

going to do a reconnect by calling this

27:08

different API endpoint instead

27:11

I'm sort of handwaving over this a

27:12

little bit because it's client side

27:14

handling for for traditionals. Um, if

27:17

there's more questions about this,

27:18

please feel free.

27:22

All right. So, that gives us resumable

27:25

streams. Um, and I'm also going to demo

27:28

uh what if we wanted to deploy this and

27:31

see it in production.

27:34

Uh, so I'm going to call this and then

27:36

we can check out a production preview

27:38

example.

27:40

In the meantime, uh the next we're going

27:44

to do is we talk about

27:47

events and resumability.

27:50

The workflows because they run the way

27:52

it runs is that every step runs on its

27:55

own serless instance in production. The

27:57

actual work workflow orchestration layer

27:59

is only called very briefly to

28:02

facilitate a step runs. What this allows

28:05

us to do is to have a workflow to spend

28:07

for any amount of time. a workflow could

28:10

wait for a week and not consume any

28:12

resources. Uh this is built into the

28:15

workflow development kit um

28:19

in a way where we can in inside a

28:21

workflow anything tag with use workflow

28:24

we can simply call sleep

28:26

three days for example

28:30

um and that would also wake us uh that

28:35

will pause the workflow for three days

28:38

and then resume where we left off. If

28:40

someone was trying to reconnect to a

28:41

stream for example, right? This was

28:43

sleep an hour, the stream would just

28:45

reconnect again to the same endpoint and

28:47

things would resume from there. So we

28:49

don't lose anything by uh losing the

28:52

instance that runs the code because we

28:54

can always restart it, resume from where

28:56

we left off.

28:58

Um and this is useful for AI agents

29:00

because we can to a tool call. uh we can

29:03

have the UI as the AI agent have a call

29:07

that says sleep any amount of time and

29:09

then use it to make an agent that that

29:12

essentially uses a crown job where it

29:13

says every day read my emails and do

29:16

this thing right so that would be sleep

29:17

one day yes

29:19

>> when the when the kind of agent goes

29:22

down that means all the state goes with

29:25

it down

29:26

>> yes so when it when it sleeps no when it

29:27

sleeps for three days

29:28

>> no then it kind of paused but when that

29:31

would be killed output is for some

29:33

reason where does the state go of that?

29:36

>> So the the way it works is that any step

29:39

call um is cached. So when you when an

29:43

input goes to a step call, we register

29:45

that as an event and we run the step and

29:48

if the step completes, we cach the

29:50

output and say this step has been run um

29:53

to completion. Right? So if it was if it

29:55

was something like this where we run the

29:56

agent first, right? Let's say we run the

29:58

agent and we run a bunch of steps. um

30:01

the state of the workflow function at

30:03

this point in time would be saved and

30:05

all of the outputs from all of the stat

30:07

calls would be saved and at the time

30:09

where we restart the workflow from this

30:11

specific line of code it'll rehydrate

30:13

the entire state and it'll just go from

30:16

here.

30:18

Um and this happens so that again we

30:21

don't have to replay any of the code of

30:22

it uh in a way that that does any actual

30:25

resource consumption.

30:27

Um

30:29

yeah, so

30:31

we can use this to make an agent that

30:33

has it's essentially a crown job again.

30:35

Um and we can use it to make agents that

30:37

run for weeks or interact with any of

30:39

your um sort of like information over

30:41

over a very long time horizon.

30:44

And

30:46

while I've been talking, we have

30:48

deployed uh our current app to the cell.

30:51

So I can check out this preview branch

30:52

for example and you can see the app is

30:53

now live online um and working just as

30:58

it usually does. And

31:02

yes it works perfectly. And if I then

31:05

again I can do

31:07

uh I can use the UI to inspect this at

31:10

any point. If I call

31:13

workflow inspect web or just workflow

31:16

web with the dash backend for cell and

31:19

dash and preview parameters for example

31:22

that'll just let us let it know where

31:24

our deployment is to be found and then

31:26

that'll spawn up the same UI and now we

31:28

can check on this run run run that's

31:31

running in production and you can see

31:32

we're getting the same kind of

31:34

information here. Um,

31:38

yeah. So, this is sort of Oh, I'm not

31:41

going to cancel the run. I could cancel

31:42

the run. Let's cancel it. Um,

31:46

this is to show that the way it works in

31:48

local locally is the exact same way that

31:51

it works in production from a conceptual

31:53

standpoint. Um, which is the UX we are

31:56

aiming for.

31:58

All right. Um, I talked a little bit

32:00

about sleep and suspend. Let us go and

32:04

write this

32:06

sleep tool call. It's going to be very

32:09

simple. Uh I'm going to go and copy the

32:14

I mean I already here but I'm going to

32:16

copy this and write it from scratch.

32:18

We're going to write a sleep

32:21

uh pool call.

32:27

I'm just going to call it sleep.ts.

32:30

And uh we're going to turn down the

32:32

input schema to be something like time

32:36

out milliseconds

32:38

and the actual run command to be

32:47

none of this and instead just call

32:50

sleep.

32:54

Um because sleep is already a step um

32:57

that we export from workflow in workflow

32:59

library. We don't need to call uh we

33:02

don't need to mark this function as use

33:04

step

33:06

but this will now uh let's see if this

33:10

is oh this should be a number. There you

33:14

go.

33:15

>> Can you see that again? Why don't you

33:16

need the use step?

33:18

>> Oh uh so this is already a step um that

33:20

we export from workflow. It's going to

33:23

be the observability will also show it

33:25

as a step which we'll see in a second.

33:28

And

33:30

um this should just work assuming the

33:32

prompt is good which we're going to

33:34

modify to be say something like

33:37

see

33:40

of this.

33:42

Um

33:44

yeah, do this. Um only use this tool if

33:49

the user directs you to do so.

33:55

All right. And get a double quote here.

33:58

There we go. And so now that this sleep

34:00

call is set up, um that should be all

34:02

that we need to do.

34:07

We'll call it run sleep command and

34:11

sleep tool. And we're going to add this

34:15

to our tools list.

34:23

And

34:26

I think I confused our compiler a little

34:29

bit or at least TypeScript.

34:33

This seems to work great. Okay, now we

34:35

have the tool. Um, and we also want the

34:37

UI to sort of display when it's

34:39

sleeping. Um, so I'm going to add I'm

34:41

going to add a another not a function to

34:46

log sleep. Uh,

34:50

this is the reason we're doing this is

34:52

we cannot write to a stream directly

34:56

from a workflow because then it wouldn't

34:58

be uh deterministic anymore because

35:00

every run of the workflow would write to

35:02

the stream again. Yeah. So I'm trying to

35:04

run the project. Um I had to create a

35:06

versel API key for the AI gateway. Did

35:08

that did that getting error that says

35:13

header is missing from the request. Do

35:15

you have the YC option enabled in the

35:18

project settings?

35:20

>> You skipped this in the beginning but

35:21

>> oh yes.

35:24

>> Yes. Our uh because this code uses uh

35:28

sandbox uh you would need to log into

35:31

this. Um my mistake uh this should be

35:34

running locally. Um if you don't use

35:35

this sandbox which uh I will uh we'll

35:39

have a branch that doesn't use this

35:40

sandbox um for after the talk.

35:44

>> For now you might

35:49

>> um at this point I'll just do it

35:50

afterwards. It's fine. So here I'm just

35:54

going to add another call to writable

35:56

and we're going to call uh we're gonna

35:59

let's see we're going to need

36:02

local ID and so now this is just going

36:06

to writes to the stream and that should

36:09

allow us to

36:11

show it in the UI correctly. Um, let me

36:15

see if I figured

36:18

the UI to correctly interpret this

36:21

packet.

36:24

Um,

36:26

there is no data sleep type which I

36:31

think might wait. Yes.

36:34

All right. So, now that I have this, um,

36:37

I can go start our app again

36:41

and

36:46

And so it loads. We can try out the

36:48

second prompt here which is sleep for 30

36:51

seconds and then return a

36:54

uh just to show that it's going to

36:55

correctly interpret the sleep call and

36:58

then

37:01

sleep. Um, it's not showing the data

37:02

packet here sadly, but we can go to the

37:08

web UI

37:10

and we can show it

37:13

has been it's engaging in the sleep call

37:16

and this is going to return after 30

37:17

seconds.

37:20

All right, so that's sleep and there's

37:23

one final thing um one final feature

37:25

that I want to show you u which is web

37:27

hooks and the ability to resume from web

37:30

hooks easily. uh implementing web host

37:32

is usually quite difficult or a headache

37:36

and in our case uh I'm going to check

37:39

out the conf /5-hooks branch and show

37:43

you that we can in the same fashion as

37:46

we do sleep we can add a new tool that

37:49

I'll just I'll just show you where the

37:50

actual tool call is um just a a log call

37:56

and then we create a web hook which is a

37:58

function we export from the workflow Uh

38:02

and we can then log the web hook URL

38:08

to the client or anywhere else and await

38:11

web hook and this will suspend for as

38:13

long as necessary to uh someone to click

38:17

on this URL and then

38:20

let's see if we can the server is

38:22

running and I can show you this uh

38:24

running hopefully

38:27

reload this and Um,

38:35

wait for wait for human approval

38:40

before starting

38:43

and call

38:45

Pokemon index.

38:49

Let's see if it happen this correctly.

38:54

Been changing branches, so I might need

38:56

to restart my server.

39:05

Um, and the way this works under the

39:07

hood is that again we'd be creating a a

39:11

URL and we're going to sleep the um the

39:16

workflow until a call comes into that

39:18

endpoint. And this comes with I'm going

39:21

to run this query. This comes with a lot

39:24

of extra features like I could also do

39:26

respond with if I wanted to. Uh this is

39:29

a full API API request handlaw. I could

39:31

respond with a request object. Uh I can

39:35

treat this as a uh again API endpoint. I

39:39

could also check the body against the

39:41

result schema for example and then only

39:44

uh resume once that matches.

39:48

So this gives you full control. Um, but

39:50

the nice thing is it does hook up the

39:52

URL internally and you can see that it's

39:55

paused waiting for a human to click on

39:56

this link and if you're running in local

39:59

host it's a local host link running in

40:00

production it will be whatever your

40:01

deployment uh URL is. Um yes about both

40:06

sleep and human approval those are like

40:08

a workflow is is purely steps and steps

40:10

always run to completion right so so

40:12

sleep is a step it's not like the

40:14

suspension of you know like some sort of

40:16

like it's not a suspension of the the

40:19

execution it's like it's it's a step

40:22

>> no it is so we model is the step in

40:24

terms for the observability and for the

40:27

for how you call it but it is an

40:29

internal feature that completely

40:31

suspends the workflow and all steps

40:32

nothing is running while to sleep. Um

40:35

you can also do sleep and another step

40:38

and you can promise them if you want. Um

40:41

it works as a step call in that sense

40:43

that it's a execution that takes a

40:44

certain amount of time. Um and you can

40:47

use promise await syntax uh to model

40:50

that but again it completely suspends

40:52

unless there is anything else running at

40:54

a time and the same for the web hook.

40:56

it's modeled as a step um for the

41:00

observability

41:01

um but it completely suspends unless you

41:03

have auto code running at the time.

41:05

>> So just from my understanding if you

41:08

have an agent running uh with a workflow

41:10

it keeps running.

41:11

>> Yeah.

41:11

>> You connect to it again let's say

41:13

through another session and you would

41:15

call sleep in this session does that

41:18

like the previous one just like whatever

41:20

it was doing just goes down. So if you

41:23

have two sessions

41:25

um so let's say we we have a coding

41:27

session right and it already built an

41:29

app and then it's sleeping for a week

41:31

right um and then we reconnect to the

41:33

stream is that the

41:34

>> no the thing is uh let's say I kick off

41:36

a work uh workflow and it's calculating

41:40

like the numbers of pi just keeps on

41:42

right but I connect to the same sandbox

41:44

and then I call sleep will it stop

41:47

calculating pi

41:49

>> um so the way you would do this in a

41:52

workflow is again let's let's see how we

41:54

would code this

41:55

>> you have a sandbox there sleep in the

41:58

sandbox

42:00

>> well you can connect to this sandbox you

42:03

connect again to the sandbox and some

42:05

thread call sleep does the whole sandbox

42:08

go

42:08

>> so the the sandbox is uh it's basel

42:11

sandbox which is a sort of just imagine

42:13

it as an EC2 instance um so this is just

42:15

a a helper for us to spin up an instance

42:18

to run this coding agent like run the

42:21

code in order to store the files

42:22

Um if you met this differently you

42:25

wouldn't have to use sandbox um and the

42:28

sleep call doesn't happen as a as a bash

42:30

call for example then two different

42:33

>> right

42:34

>> like an orchestration thing and then

42:36

when you're actually in this box you you

42:38

call sleep in a sandbox you're

42:40

>> okay so there are two different

42:41

>> right so so there is sleep that you

42:44

could call from a terminal um in the

42:46

sandbox as a as a as a terminal command

42:48

or there sleep from the workflow which

42:50

suspends the workflow

42:54

Uh yeah so we have we have these

42:57

features for for web hooks right and we

42:59

can see that after I clicked on the URL

43:01

it resumed and then coded me a Pokédex

43:05

um that is all of the features we're

43:08

going to in the session and I think we

43:11

have ample time for Q&A about 20 minutes

43:14

at least

43:17

please go for

43:18

>> how would I spin up claude code session

43:21

with this

43:23

>> a cloud co session

43:26

remotely or are you

43:27

>> no kind of run and kick it off as an

43:29

agent doing certain stuff um is that

43:33

possible and then kind of orchestrate

43:35

that as agents

43:36

>> that is possible so cloud code uh is um

43:41

if you're talking about the app like a

43:42

tonal app right cloud code then that

43:45

doesn't use a lot of the workflow

43:46

features internally um so it's hard to

43:48

isolate that or know where the oxidation

43:51

There is you could write your own

43:53

version of uh cloud code or take the

43:55

plot code source code and add workflow

43:59

and step um for the calls and that would

44:02

then run as as a workflow in the cloud.

44:04

There's no way to say like okay I have

44:06

my steps you know spin up claw work uh

44:10

kind of code type this command and wait

44:14

for anything that would be a versel

44:15

workflow but how would I actually boot

44:18

drop it like code it

44:21

>> is one command told right so you know

44:23

what you're asking

44:23

>> if you so if you're calling cloud code

44:26

uh in a um so made as a confusion of

44:28

like where this is running right for a

44:30

coding agent here if the coding agent

44:32

runs make the right for like creating

44:35

creating a folder that make the command

44:37

runs in a step but it runs against a

44:40

like in a sandbox there sandbox being a

44:43

VM and so this VM state is not managed

44:45

by the workflow itself um so if you call

44:48

cloud code on the VM that's essentially

44:51

treated like an SSH session but if you

44:54

run any any agents or steps within the

44:56

workflow right those steps are going to

44:58

be resumable um and observable through

45:01

the workflow pattern

45:04

Um, another question, how do I control

45:07

um what my agent has access to from

45:11

going out to the internet doing stuff?

45:14

>> This would be uh whatever you're

45:16

whatever you're already doing for the

45:18

agent, right? If you if you in the end

45:21

you're going you're going going to be

45:22

doing tool calls and stream calls to the

45:25

LM provider, right?

45:27

um that is that is in your code

45:29

presumably already and whatever you're

45:32

already using to control permissions

45:34

there like your tool calls for example

45:35

right if your tool call uh allows you to

45:40

delete a resource in S3 for example then

45:43

you as

45:45

call uh can write whatever code you want

45:48

uh in the usual way that

45:52

>> it's my job to implement it but it's not

45:54

that it has some wrappers by the end

45:56

Yeah, all in the sandboxes.

45:59

>> Workflows is a general orchestration

46:00

layer for durable execution um and

46:03

doesn't necessarily provide a sandbox

46:04

for running code or um like running

46:08

third party code or running agent code

46:09

or making files. Uh that's something

46:11

that the sandbox is good for because

46:13

every sandbox instantiation is a new VM

46:16

um that only lasts for as long as your

46:18

session lasts.

46:21

>> Yes.

46:22

>> Yeah. So uh if I'm running workflows uh

46:26

and I'm like creating a lot of agent uh

46:28

workflows through my brother uh how does

46:33

that do does that get queued up on your

46:35

system? How does that get run? Is there

46:38

rate domain or currency and controls

46:40

that we can uh use?

46:44

>> Yes. So this is this is uh this goes

46:47

into sort of uh some of the patterns

46:52

that all of this is going to be

46:53

supported um and for the most part is

46:55

supported right now which is that if

46:56

you're deploying for example to go right

46:58

and as usual if you do nextjs every

47:01

deploy is a separate uh like live URL

47:05

right that if you call it spawns up a

47:07

serverless instance and so your

47:10

workflows are bound to the deployment.

47:12

So if you have something that something

47:14

very nice that you get here is if you an

47:16

agent and it runs for a week but you

47:18

deploy five times in during this week

47:21

those new deploys are going to be

47:22

isolated from the original workflow and

47:25

the original workflow is going to run to

47:26

completion and then any new workflow

47:28

will run on the new deployments and

47:30

we'll also allow upgrading between

47:32

those. So if you have a a workflow that

47:34

runs for a year, right? Because it's

47:35

like every month give me a summary of so

47:37

and so, right? But you have new code and

47:40

you want the workflow to uh you know

47:42

take its current state and use the new

47:44

code for the workflow. Um there's going

47:47

to be an upgrade button in the UI that

47:49

checks for compatibility between the old

47:51

workflow and the new workflow by

47:53

checking all of the step signatures and

47:55

all of the existing events and then you

47:57

can upgrade the workflow. Um or you can

47:59

currently already cancel and rerun with

48:01

the with the new workflow.

48:03

>> Um is there a timeout for those workflow

48:06

steps?

48:08

>> Oh

48:08

>> yes. So uh if you're doing serless right

48:11

and whatever platform you're on whether

48:12

it be like lambda or something else or

48:14

or uh your serless functions are going

48:17

to have timeouts. The nice thing is that

48:19

every step runs in its own serless

48:21

function. So the timeouts only apply to

48:24

the stats. So if one of individual step

48:26

you have runs the risk of running more

48:29

than five minutes maybe 15 minutes

48:31

depending on platform um then you can

48:34

split into two steps um or if it's if it

48:36

runs the timeout right it'll fail it'll

48:38

retry maybe the will be faster um and

48:41

you'll see in the UI that oh this step

48:43

is being retrieded after 15 minutes a

48:45

bunch of times right presumably because

48:46

it's failing and then you can go and uh

48:49

split it into two steps upgrade the

48:52

workflow and it'll just continue from

48:57

And uh yeah the other point was uh

49:00

around queuing workflows like I trigger

49:02

the agent a bunch of times.

49:03

>> Yeah.

49:04

>> Does it get cued? Like how does that

49:07

process?

49:08

>> Right. You can model this in in

49:09

different ways. Uh right now again we're

49:11

doing this from like a API route where

49:14

every call to this API route will create

49:16

a new workflow. Um that is mostly again

49:20

the only the only the only interactable

49:22

output you have is a stream in this

49:24

case. Um so it'll do things it'll write

49:26

to the stream. Nobody looks at the

49:28

stream. We don't know the work before is

49:30

running. Uh you can kick off 10 of

49:32

these, right? Um and they're going to be

49:35

running in the background. Um there is

49:37

essentially no limit to how many you can

49:38

create because they all run in serless

49:40

functions. So you can scale for as much

49:42

compute as there is in your provider. um

49:44

which is a lot of cute and um you can

49:49

also list active runs right there's an

49:51

API here for doing C interfacing with

49:54

your runs look at all of the runs that

49:55

are running look at which version

49:57

they're on uh what step they're on um

49:59

cancel them I hope that answers your

50:02

question oh concurrency yes um you can

50:05

also so right now it's infinite

50:07

concurrency but uh very soon we'll add

50:11

per step or per workflow concurrency

50:13

where you can say This workflow is only

50:15

supposed to run at most 10 times at the

50:17

same time and any extra Q addition gets

50:22

like any extra start gets cued so that

50:24

it will wait for those 10 to uh reduce

50:27

and then slide in. You can also use that

50:29

to have a free tier for example on your

50:32

product where there's 10 instances

50:34

running for your free tier at any one

50:36

point and some people that come in later

50:38

will wait for the queue but your pro

50:40

tier has infinite concurrency.

50:44

>> Yeah.

50:46

>> Can I roll back steps in a way that

50:49

let's say I have 10 steps but in step

50:51

seven I think like okay let's go back to

50:53

step three. Would that be possible to

50:56

like reset the state of the workflow or

50:58

>> you can technically do this do this? We

51:02

current we don't currently support it

51:04

but it would be very easy to implement

51:05

because uh you have every step again the

51:08

inputs and outputs are cached and we can

51:10

enter the workflow at any point and sort

51:12

of play from there. So we'd need to

51:14

expose this in the in the UI to as a

51:16

function to resume from step so and so.

51:18

But yes, that would be possible. more

51:20

more likely what you want to do because

51:22

you control the workflow.

51:25

So you wanted to log there and use this

51:29

JavaScript

51:31

and might have to

51:34

step into state or do something just

51:37

keep growing.

51:42

Maybe my second question. So if you go

51:44

through the steps you said, okay, you're

51:46

passing out input and outputs kind of

51:48

across and that's kind of what get

51:50

cached. Is there like a way to attach

51:54

metadata or does it always have to be in

51:56

kind of the input outputs of the

51:58

function?

51:58

>> You can also attach metadata. uh we'll

52:01

have a tagging API soon where you can

52:03

add arbitary tags to the workflow at any

52:06

point in the workflow run and you can

52:08

use those tags also to maybe decide

52:10

whether to early or dd duplicate your

52:12

runs. Um yeah.

52:17

>> Yes.

52:17

>> About the deployment are we tied to

52:20

versel or is it possible to like

52:23

>> as I mentioned before uh so there

52:25

there's two aspects to this. There's the

52:26

the front end side of the framework uh

52:29

the docs are on use workflow.dev. Uh you

52:32

can see for the front end sides um which

52:35

is also sort of the the uh API layer it

52:39

might work with. Uh we currently support

52:41

all of these platforms.

52:43

um and more coming soon. And then

52:46

there's separately the deployment target

52:47

right next.js JS you can deploy to

52:49

anything right now right this would work

52:51

with anything you can deploy XJS2 for

52:53

example or any of these other frameworks

52:56

um and we have implementations first

52:59

party implementation for a Postgres

53:02

example that uses Postgres as the

53:03

dability layer um and as we'll be

53:06

building this out and community comes in

53:08

we'll have support for essentially any

53:10

back end um because underneath the

53:12

TypeScript framework connects to any

53:14

storage or Q layer so anything that

53:17

provides a storage a database uh or AQ

53:20

can be used the back end for for this

53:26

>> related question for the observability

53:29

we also like providers to data dog stuff

53:33

>> yeah so uh we we have a uh multiple

53:36

things we have an an API that you can

53:39

use to to uh access data directly um and

53:42

we also have open source UI components

53:44

that you can use to display it and then

53:46

you can export this to data Um if you

53:49

want. Yeah.

53:59

>> You talked about screen a little bit and

54:01

talked about how it essentially like

54:04

job. Uh do is there more scheduling and

54:08

chron controls within workflow? So uh

54:11

because it's just typescript uh if

54:14

you're in a workflow um you can do

54:18

something like let's say we call sleep

54:20

for example right this this would just

54:21

be resume in a sorry resume in one day

54:24

but what you can also do is uh this is

54:27

just a promise or you can treat it as a

54:29

promise so you can do

54:33

while true sleep one day and then uh you

54:38

know do your code and it'll run once a

54:40

If you wanted to run once a day at 2

54:43

a.m. um you could you could say you know

54:46

how much time

54:49

to you know 1:00 a.m. tomorrow. Thank

54:53

you AI. And then you know done. Um and

54:58

you could also

55:00

wake up every hour do some checks

55:02

whether you actually want to run the

55:04

rest of the code. If not go back to

55:06

sleep. Um anything you can do with con

55:08

to do here. And if you want again

55:09

concurrency controls something um or any

55:12

kind of other deterministic controls you

55:14

have control flow in Typescript here.

55:17

You can check check external um APIs.

55:20

for example, um which you have to wrap

55:22

in a step, but you can make fetch calls

55:24

if you want to actually check data and

55:26

then determine from there.

55:29

>> So if you if you wanted to do a uh agent

55:32

that runs every once in a while every

55:34

day, you could have a scheduling wrapper

55:37

scheduling workflow that launches

55:38

another agent workflow

55:40

>> also. Yeah, you can you can you can

55:42

start workflows from workflows or you

55:44

could do this right where you uh sleep a

55:47

day and then call your agent and then

55:50

depending on the the on the stream you

55:51

want to right this is all right in the

55:53

same stream presumably you don't want

55:55

that presum maybe you can also uh

55:58

thatable

55:59

allows you to do namespace right uh one

56:04

um and you can get a new writable here

56:06

and then every time it runs you can have

56:08

a new stream that has a deterministic uh

56:10

name and you can choose which stream to

56:13

connect to.

56:14

>> Yeah.

56:17

>> Is there cancellation logic? Like say I

56:20

have something waiting for a long time

56:21

and then I decide to not have that be a

56:23

thing. How can I just like stop an

56:25

existing sleep from waking,

56:27

>> right? So you can cancel your workflows

56:29

from the observability UI or from the

56:31

from the API or the CLI. um all of those

56:34

avenues uh have you can call cancel or

56:37

you can also say well I don't even know

56:39

if I want to sleep on the end of the

56:40

zoom what you can do is do a uh let me

56:44

remove this part here you can do

56:46

something like

56:50

you know await promise grace and you can

56:54

do the sleep one day and you can do some

56:57

other actually human approval maybe wake

57:00

up earlier if a human clicks a button

57:02

than the one Okay. Um, there you go.

57:08

>> Yes.

57:09

>> Um, if you have multiple agents running,

57:11

uh, what would be your advised way of

57:14

having them communicate with each other?

57:17

>> Um,

57:20

if if you're

57:22

sort of depends on what kind of

57:24

communication you're looking for.

57:25

>> Firing things off and they're working,

57:27

but I wouldn't sure there was. So in

57:30

steps um you have access to

57:34

all code APIs or

57:38

NodeJS API fetch etc. You can have a

57:40

database, right? If you want to automate

57:42

over your own data source, you can have

57:43

a database. Um, if you want to have

57:45

multiple agents, um, you can, uh, use

57:50

one, you can use some of the same

57:52

streams to write to and share a stream.

57:55

Um

57:57

yeah,

58:03

I guess it's up to us ultimately with

58:05

our steps that they're like I demp it in

58:07

and if they have side effects when they

58:09

fail halfway that it's well behaved like

58:11

that's that's not at your orchestration

58:13

layer like that's up to us,

58:15

>> right? for the workflow layer, we

58:17

guarantee that there's no side effects

58:19

because if you try to import some code

58:21

that does side effect, I think it'll

58:23

just it'll just say like can't compile,

58:25

doesn't you know, don't do it. Um,

58:27

>> that was true for workflows, but for

58:29

steps

58:29

>> for steps, it can have side effects.

58:31

That's sort of the point.

58:32

>> So, it's up to us like if it fails, we

58:34

need to make sure that transactional and

58:36

it's rerunnable and

58:37

>> identity. There's some there's some uh

58:39

there's some error controls you can add

58:41

here where if a step fails, it'll

58:43

usually fail uh with a an error that

58:46

tells the workflow station layout that

58:48

you can retry it. You can also catch

58:50

this error and say, well, if it's a you

58:52

know this kind of error, don't retry it.

58:54

Instead, signal to the human to do

58:56

something or try this other avenue.

58:59

Yeah.

59:14

See there's something else.

59:18

>> Do you have one of the branches that has

59:20

like the complete code for what you just

59:22

did?

59:22

>> Yes. So, uh they all built on top of

59:26

each other. So, the conflooks

59:28

branch has the human approval tool

59:31

called the sleep tool call. resumable

59:34

streams um and using web flow.

59:41

>> Uh I will

59:44

see how I can post one general access

59:48

>> just tweet it out.

59:50

>> Yes, we'll do that.

59:52

>> Uh the workflows are in beta and so

59:57

>> Yes. Yeah. Um

60:01

>> okay. Yeah. Uh yes, I forgot to mention

60:03

this important uh workflow devel

60:10

I believe and we have a a GitHub

60:24

using production especially durable

60:25

agent stuff

60:29

>> internally we have I think more than 1

60:31

million workflows have been run on on

60:33

>> a day. Yeah,

60:36

>> it's mostly just like getting

60:39

the API to be stable and a bunch of

60:41

issues. But one of the things I love is

60:42

that we actually have more than issues.

60:46

But uh

60:49

>> yeah,

60:51

>> if there's any feature that you that you

60:53

need or that you really want to see, uh

60:54

we have an RFC section on GitHub uh

60:57

discussions for upcoming features,

61:00

things that we'll ship by GA or shortly

61:03

afterwards. And then open issues, right?

61:06

Um where you can add any issue and

61:08

presumably we'll be able to it soon or

61:10

someone from the community. Again, this

61:11

is uh all of the adapters that help

61:15

workflow develop run on any kind of

61:17

cloud back end or your homebrew back

61:20

end. All of those adapters are also open

61:23

source. So, you can see exactly what's

61:25

happening and you can connect it to your

61:26

own back end and only the source um just

61:29

looking at that code and we'll be happy

61:31

to help you.

61:33

Can you talk about uh

61:40

>> uh yeah um what would you like to know

61:43

>> the road map for like

61:46

>> right so for versioning um I talked a

61:48

little bit about about uh the ability to

61:51

upgrade runs across versions right uh

61:53

versioning is going to be very simple

61:55

where we have a crowd interface for all

61:57

of the versions that you have created

62:00

which for most people will be a

62:01

deployment right if you deploy your

62:03

um you know CI deploys your code to a

62:06

preview environment or production uh

62:07

every deployment will be one version um

62:10

and you can list those versions at any

62:13

point uh using the the workflow API and

62:17

the run will know which version it's

62:19

running on and you can call run.upgrade

62:21

upgrade to see if it's compatible with a

62:24

new version to upgrade it to that

62:25

version and I know any any more things

62:30

>> version

62:32

>> no yeah so so every every deployment uh

62:36

gets its own URL and not just in basel

62:38

but presumably in your if you go to AWS

62:41

lender for example right uh every

62:44

deployment has its own URLs so the web

62:46

hooks would apply to its own URLs um

62:49

which means that you don't need worry

62:51

about versioning except for tagging a

62:53

version when you first create the

62:54

deploy. Um and then whatever you think

62:58

is you want to be your main version is

63:01

the one you route to via your public

63:03

API.

63:04

>> Yeah, I think um sorry

63:08

obviously I used to work at my

63:11

experience in this stuff. I think a lot

63:13

of people unfortunately it's like

63:16

isolation of but sometimes you want to

63:19

sort of fix in place things that have

63:21

been a while.

63:22

>> Yeah. Migrations almost like agent

63:23

migrations to new version.

63:26

>> Yeah. So this is the same as as

63:28

upgrading in that sense, right? But if

63:30

you have a bunch of runs that are all on

63:32

a certain version and you have ship new

63:33

code and you want all those runs to be

63:35

upgraded to the new version or migrated,

63:37

right? Um, in the UI you'll be able to

63:40

select however many runs you want or for

63:42

the CLI you want to be able to get a

63:44

list and then say for these 20 IDs I

63:46

want to upgrade the run to this version.

63:49

Uh, will it'll do an internal check of

63:51

of can I resume these uh workflows from

63:56

a certain point? um like can I migrate

63:58

them in place sort of because the step

64:00

signatures overlap or if not it'll offer

64:03

you the option to cancel all of the

64:05

existing runs and rerun them on a new

64:07

version of the same input. Um if you

64:10

write your code in a way that's

64:11

compatible again um there's there's

64:13

going to be different options for for in

64:16

place migrations.

64:17

>> How would it detect that just by code

64:19

parts not being changed? So because we

64:21

have because we're essentially a

64:22

compiler plugin uh we can get full a uh

64:27

compatibility and and we are saving this

64:29

a uh

64:32

the inputs and outputs signatures um to

64:34

a manifest that we're uploading for the

64:36

versions and so for every version we can

64:37

tell what are the signatures for every

64:40

uh step and for the workflow itself and

64:43

all the other things that are happening

64:44

in between.

64:46

>> Another thing here is the workflow

64:47

function itself.

64:49

So yes, we played a whole bunch of times

64:51

during execution do anyway.

64:55

>> So when you want to upgrade

64:59

your event,

65:01

>> it's kind

65:05

of the code that you've got on the event

65:08

against it.

65:12

>> Sure.

65:14

There's a lot of variations between kind

65:16

of I do a step all the previous steps

65:18

stayed the same or you know this one got

65:21

changed. So it's like you like if

65:24

everything's done automatically it feels

65:25

like okay I could go down immediately

65:27

with all my agents or up

65:29

>> there's two ways you could there's two

65:30

ways you could be versioning

65:33

and I think the thing with

65:36

is you build for a platform where you

65:38

assume that the code your code is always

65:40

going to evolve in the same place. So

65:42

what we've seen is you end up with as

65:44

you start your first version of your

65:45

workload that you ship but as you start

65:47

making updates to you starting new

65:49

version your code now has all the stuff

65:51

in there that has

65:54

you have no guarantees of what version

65:57

running on the actual code that you're

65:59

running. The default assumption is that

66:01

my code could be running an event log

66:04

anyway and you end up with starts great

66:07

and then you have to do model

66:13

>> but it was the same with like killing

66:14

and sustaining

66:18

already had

66:20

forever. there's a natural step to go

66:22

say cool we're just gonna assume that

66:23

you you push a new version of the

66:25

workflow you pin everything

66:28

and so you don't have to worry about

66:30

that mental model that

66:33

code but instead it's time to go up push

66:37

button

66:38

I can go in

66:41

or even choose like you know

66:43

theoretically choose exactly how much of

66:44

that button get

66:47

there's a lot of stuff that you can do

66:48

on top since you have But what's nice is

66:51

that's that's a hard US and you know for

66:54

us to build when done well

67:00

hopefully very

67:07

>> I don't know we're close to done

67:10

>> I think we're close to done

67:12

>> uh we'll be sticking around for more

67:13

questions so uh

67:16

>> I guess okay so let's say I'm a third

67:18

party like But I think the other part is

67:21

observability.

67:23

Um I don't I I like poked around in I

67:26

don't see like much of a dashboard. I

67:30

expect that obviously you're going to

67:31

build one, right? Uh and then I also

67:33

want to import it into my data dog. See

67:36

there not a data dog but hey what's this

67:40

supposed

67:41

>> uh open telemetry spans uh which we'll

67:44

you know be able to emit um we'll add

67:46

some context to the spans by default

67:48

presumably. Uh so if you if you just

67:51

pipe your spans through data dog it'll

67:53

already have a lot of information on the

67:54

steps and event log. Um and you can also

67:57

submit your own uh telemetry obviously.

68:00

>> So is that the plan or is it you have

68:02

the first party?

68:03

>> The plan is that we will we will first

68:05

party support adding some of the like

68:07

all of the sort of step and event log

68:09

related context. Um will uh presumably

68:13

export a helper to add some of these

68:15

information to the spans. Um and then

68:18

every all information you want to tag in

68:19

there is up to you.

68:23

>> Can I uh attach like secrets to workflow

68:28

in a way that when I need to update them

68:30

they kind like you know

68:31

>> Yeah. So uh for one like right now you

68:34

can you can inspect all of the input and

68:36

output data right and it's obviously uh

68:38

for you as a someone with access to the

68:40

API uh which someone consuming the

68:42

workflow or starting the workflow

68:44

through web API wouldn't usually have

68:46

>> no

68:48

steps in steps

68:51

>> yeah so the the workflows run in the

68:53

same deployment as as it would usually

68:54

do and has access to the process uh

68:57

environment right so you can inject

68:59

environment levels the way you would

69:00

usually do um and as as long as long as

69:02

you don't log them which again

69:03

presumably you wouldn't do any anyway um

69:06

it's the same way as an API endpoint and

69:08

then if you want your data to be secret

69:11

right um right right now we expose it in

69:13

observability um if you have access but

69:16

we also will allow in the future to do

69:18

end to end encryption for any data store

69:21

>> right then we'll uh close the session

69:24

but we'll be around a little bit more

69:25

for questions if you want to you know

69:27

look over

69:28

She lost

69:43

heat.

Interactive Summary

The video introduces the open-source Workflow Development Kit, designed to simplify moving local AI agents to production by providing durability, reliability, and observability. It achieves this by separating agent code into deterministic workflow orchestration and isolated, retriable steps. The session demonstrates integrating the kit into a Next.js coding agent, highlighting features like resumable streams, long-running processes using sleep functionality, and human-in-the-loop workflows via webhooks.

Suggested questions

10 ready-made prompts