diff --git a/mint.json b/mint.json
index ca985b26..98a2362e 100644
--- a/mint.json
+++ b/mint.json
@@ -1438,6 +1438,7 @@
"workflow/howto/monitor",
"workflow/howto/security",
"workflow/howto/parallel-runs",
+ "workflow/howto/invoke",
"workflow/howto/schedule",
"workflow/howto/changes",
"workflow/howto/local-development",
@@ -1467,6 +1468,7 @@
"pages": [
"workflow/examples/allInOne",
"workflow/examples/waitForEvent",
+ "workflow/examples/invoke",
"workflow/examples/customerOnboarding",
"workflow/examples/authWebhook",
"workflow/examples/paymentRetry",
diff --git a/workflow/basics/context.mdx b/workflow/basics/context.mdx
index c1d596f0..6fd05c3a 100644
--- a/workflow/basics/context.mdx
+++ b/workflow/basics/context.mdx
@@ -525,6 +525,27 @@ More details about the `Waiter` object:
+### context.invoke
+
+Triggers another workflow run and waits for its completion.
+The workflow continues when the invoked workflow finishes, whether successfully, with failure, or is canceled.
+The response is the data returned by the invoked workflow, if any is returned.
+
+```ts
+export const { POST } = serve<{ topic: string }>(async (context) => {
+
+ const {response, isFailed, isCanceled} = await context.invoke("invoke another workflow", {
+ workflow: anotherWorkflowObject,
+ body: "test",
+ header: {...}
+ });
+
+})
+```
+
+Only workflows that served together can invoke each other. To learn more about how you can serve multiple workflows together,
+checkout [Invoke other workflows](/workflow/howto/invoke) guide.
+
### context.cancel
diff --git a/workflow/howto/invoke.mdx b/workflow/howto/invoke.mdx
new file mode 100644
index 00000000..a7ba5655
--- /dev/null
+++ b/workflow/howto/invoke.mdx
@@ -0,0 +1,57 @@
+---
+title: "Invoke other workflows"
+---
+
+You can start another workflow run inside a workflow and await its execution to complete.
+This allows to orchestrate multiple workflows together without external syncranization.
+
+```typescript
+const { response, isFailed, isCanceled } = await context.invoke("analyze-content", {
+ workflow: analyzeContent,
+ body: {/**/},
+ headers: {/**/}
+})
+```
+
+As you may notice, we pass a workflow object to the invoke function. This object is initialized using the `createWorkflow()` function.
+
+Normally, workflows are initialized with `serve()` method and exposed as a standalone route in your application.
+However, when workflows are defined separately using `serve()`, type safety is not guaranteed.
+
+To ensure type safety for request and response when invoking other workflows, we introduced the `createWorkflow()` function.
+`createWorkflow()` returns a referenceable workflow object that can be used in `context.invoke()`.
+
+```typescript
+import { WorkflowContext } from "@upstash/workflow";
+import { create, serve } from "@upstash/workflow/nextjs";
+
+// 👇 anotherWorkflow: (string) => number
+const anotherWorkflow = createWorkflow(async (context: WorkflowContext) => {
+
+ await context.run("step-1", () => {
+ // Execute any business logic...
+ }),
+
+ return {message: "This is the data returned by workflow"}
+});
+
+const someWorkflow = createWorkflow(async (context) => {
+ // 👇 type(response) = {message: string}
+ const { response } = await context.invoke("invoke ", {
+ workflow: anotherWorkflow,
+ // 👇 type(body) = string
+ body: "user-1"
+ }),
+});
+
+export const { POST } = serve([someWorkflow, anotherWorkflow])
+```
+
+`createWorkflow()` does not expose your workflow like `serve()`, it just initializes the workflow object.
+To be able to use the workflow, they must be exposed with `serve([])` function.
+
+
+If workflows are going to be invoke each other, they must be exposed in the same `serve` endpoint.
+
+If you pass a workflow object which is initialized with `createWorkflow()` but not exposed inside the same `serve`, you will get a runtime error.
+