{
+ const { sessionId, abortController } = stream;
+
+ try {
+ const url = `/api/chat/sessions/${sessionId}/stream`;
+ const body = JSON.stringify({
+ message,
+ is_user_message: isUserMessage,
+ context: context || null,
+ });
+
+ const response = await fetch(url, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "text/event-stream",
+ },
+ body,
+ signal: abortController.signal,
+ });
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ throw new Error(errorText || `HTTP ${response.status}`);
+ }
+
+ if (!response.body) {
+ throw new Error("Response body is null");
+ }
+
+ const reader = response.body.getReader();
+ const decoder = new TextDecoder();
+ let buffer = "";
+
+ while (true) {
+ const { done, value } = await reader.read();
+
+ if (done) {
+ notifySubscribers(stream, { type: "stream_end" });
+ stream.status = "completed";
+ return;
+ }
+
+ buffer += decoder.decode(value, { stream: true });
+ const lines = buffer.split("\n");
+ buffer = lines.pop() || "";
+
+ for (const line of lines) {
+ const data = parseSSELine(line);
+ if (data !== null) {
+ if (data === "[DONE]") {
+ notifySubscribers(stream, { type: "stream_end" });
+ stream.status = "completed";
+ return;
+ }
+
+ try {
+ const rawChunk = JSON.parse(data) as
+ | StreamChunk
+ | VercelStreamChunk;
+ const chunk = normalizeStreamChunk(rawChunk);
+ if (!chunk) continue;
+
+ notifySubscribers(stream, chunk);
+
+ if (chunk.type === "stream_end") {
+ stream.status = "completed";
+ return;
+ }
+
+ if (chunk.type === "error") {
+ stream.status = "error";
+ stream.error = new Error(
+ chunk.message || chunk.content || "Stream error",
+ );
+ return;
+ }
+ } catch (err) {
+ console.warn("[StreamExecutor] Failed to parse SSE chunk:", err);
+ }
+ }
+ }
+ }
+ } catch (err) {
+ if (err instanceof Error && err.name === "AbortError") {
+ notifySubscribers(stream, { type: "stream_end" });
+ stream.status = "completed";
+ return;
+ }
+
+ if (retryCount < MAX_RETRIES) {
+ const retryDelay = INITIAL_RETRY_DELAY * Math.pow(2, retryCount);
+ console.log(
+ `[StreamExecutor] Retrying in ${retryDelay}ms (attempt ${retryCount + 1}/${MAX_RETRIES})`,
+ );
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
+ return executeStream(
+ stream,
+ message,
+ isUserMessage,
+ context,
+ retryCount + 1,
+ );
+ }
+
+ stream.status = "error";
+ stream.error = err instanceof Error ? err : new Error("Stream failed");
+ notifySubscribers(stream, {
+ type: "error",
+ message: stream.error.message,
+ });
+ }
+}
diff --git a/autogpt_platform/frontend/src/components/contextual/Chat/stream-utils.ts b/autogpt_platform/frontend/src/components/contextual/Chat/stream-utils.ts
new file mode 100644
index 0000000000..4100926e79
--- /dev/null
+++ b/autogpt_platform/frontend/src/components/contextual/Chat/stream-utils.ts
@@ -0,0 +1,84 @@
+import type { ToolArguments, ToolResult } from "@/types/chat";
+import type { StreamChunk, VercelStreamChunk } from "./chat-types";
+
+const LEGACY_STREAM_TYPES = new Set
([
+ "text_chunk",
+ "text_ended",
+ "tool_call",
+ "tool_call_start",
+ "tool_response",
+ "login_needed",
+ "need_login",
+ "credentials_needed",
+ "error",
+ "usage",
+ "stream_end",
+]);
+
+export function isLegacyStreamChunk(
+ chunk: StreamChunk | VercelStreamChunk,
+): chunk is StreamChunk {
+ return LEGACY_STREAM_TYPES.has(chunk.type as StreamChunk["type"]);
+}
+
+export function normalizeStreamChunk(
+ chunk: StreamChunk | VercelStreamChunk,
+): StreamChunk | null {
+ if (isLegacyStreamChunk(chunk)) return chunk;
+
+ switch (chunk.type) {
+ case "text-delta":
+ return { type: "text_chunk", content: chunk.delta };
+ case "text-end":
+ return { type: "text_ended" };
+ case "tool-input-available":
+ return {
+ type: "tool_call_start",
+ tool_id: chunk.toolCallId,
+ tool_name: chunk.toolName,
+ arguments: chunk.input as ToolArguments,
+ };
+ case "tool-output-available":
+ return {
+ type: "tool_response",
+ tool_id: chunk.toolCallId,
+ tool_name: chunk.toolName,
+ result: chunk.output as ToolResult,
+ success: chunk.success ?? true,
+ };
+ case "usage":
+ return {
+ type: "usage",
+ promptTokens: chunk.promptTokens,
+ completionTokens: chunk.completionTokens,
+ totalTokens: chunk.totalTokens,
+ };
+ case "error":
+ return {
+ type: "error",
+ message: chunk.errorText,
+ code: chunk.code,
+ details: chunk.details,
+ };
+ case "finish":
+ return { type: "stream_end" };
+ case "start":
+ case "text-start":
+ return null;
+ case "tool-input-start":
+ return {
+ type: "tool_call_start",
+ tool_id: chunk.toolCallId,
+ tool_name: chunk.toolName,
+ arguments: {},
+ };
+ }
+}
+
+export const MAX_RETRIES = 3;
+export const INITIAL_RETRY_DELAY = 1000;
+
+export function parseSSELine(line: string): string | null {
+ if (line.startsWith("data: ")) return line.slice(6);
+ return null;
+}
diff --git a/autogpt_platform/frontend/src/components/contextual/Chat/useChat.ts b/autogpt_platform/frontend/src/components/contextual/Chat/useChat.ts
index cf629a287c..124301abc4 100644
--- a/autogpt_platform/frontend/src/components/contextual/Chat/useChat.ts
+++ b/autogpt_platform/frontend/src/components/contextual/Chat/useChat.ts
@@ -2,7 +2,6 @@
import { useSupabase } from "@/lib/supabase/hooks/useSupabase";
import { useEffect, useRef, useState } from "react";
-import { toast } from "sonner";
import { useChatSession } from "./useChatSession";
import { useChatStream } from "./useChatStream";
@@ -27,6 +26,7 @@ export function useChat({ urlSessionId }: UseChatArgs = {}) {
claimSession,
clearSession: clearSessionBase,
loadSession,
+ startPollingForOperation,
} = useChatSession({
urlSessionId,
autoCreate: false,
@@ -67,38 +67,16 @@ export function useChat({ urlSessionId }: UseChatArgs = {}) {
],
);
- useEffect(() => {
- if (isLoading || isCreating) {
- const timer = setTimeout(() => {
- setShowLoader(true);
- }, 300);
- return () => clearTimeout(timer);
- } else {
+ useEffect(
+ function showLoaderWithDelay() {
+ if (isLoading || isCreating) {
+ const timer = setTimeout(() => setShowLoader(true), 300);
+ return () => clearTimeout(timer);
+ }
setShowLoader(false);
- }
- }, [isLoading, isCreating]);
-
- useEffect(function monitorNetworkStatus() {
- function handleOnline() {
- toast.success("Connection restored", {
- description: "You're back online",
- });
- }
-
- function handleOffline() {
- toast.error("You're offline", {
- description: "Check your internet connection",
- });
- }
-
- window.addEventListener("online", handleOnline);
- window.addEventListener("offline", handleOffline);
-
- return () => {
- window.removeEventListener("online", handleOnline);
- window.removeEventListener("offline", handleOffline);
- };
- }, []);
+ },
+ [isLoading, isCreating],
+ );
function clearSession() {
clearSessionBase();
@@ -117,5 +95,6 @@ export function useChat({ urlSessionId }: UseChatArgs = {}) {
loadSession,
sessionId: sessionIdFromHook,
showLoader,
+ startPollingForOperation,
};
}
diff --git a/autogpt_platform/frontend/src/components/contextual/Chat/useChatDrawer.ts b/autogpt_platform/frontend/src/components/contextual/Chat/useChatDrawer.ts
deleted file mode 100644
index 62e1a5a569..0000000000
--- a/autogpt_platform/frontend/src/components/contextual/Chat/useChatDrawer.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-"use client";
-
-import { create } from "zustand";
-
-interface ChatDrawerState {
- isOpen: boolean;
- open: () => void;
- close: () => void;
- toggle: () => void;
-}
-
-export const useChatDrawer = create((set) => ({
- isOpen: false,
- open: () => set({ isOpen: true }),
- close: () => set({ isOpen: false }),
- toggle: () => set((state) => ({ isOpen: !state.isOpen })),
-}));
diff --git a/autogpt_platform/frontend/src/components/contextual/Chat/useChatSession.ts b/autogpt_platform/frontend/src/components/contextual/Chat/useChatSession.ts
index 553e348f79..936a49936c 100644
--- a/autogpt_platform/frontend/src/components/contextual/Chat/useChatSession.ts
+++ b/autogpt_platform/frontend/src/components/contextual/Chat/useChatSession.ts
@@ -1,6 +1,7 @@
import {
getGetV2GetSessionQueryKey,
getGetV2GetSessionQueryOptions,
+ getGetV2ListSessionsQueryKey,
postV2CreateSession,
useGetV2GetSession,
usePatchV2SessionAssignUser,
@@ -58,6 +59,7 @@ export function useChatSession({
query: {
enabled: !!sessionId,
select: okData,
+ staleTime: 0,
retry: shouldRetrySessionLoad,
retryDelay: getSessionRetryDelay,
},
@@ -101,6 +103,125 @@ export function useChatSession({
}
}, [createError, loadError]);
+ // Track if we should be polling (set by external callers when they receive operation_started via SSE)
+ const [forcePolling, setForcePolling] = useState(false);
+ // Track if we've seen server acknowledge the pending operation (to avoid clearing forcePolling prematurely)
+ const hasSeenServerPendingRef = useRef(false);
+
+ // Check if there are any pending operations in the messages
+ // Must check all operation types: operation_pending, operation_started, operation_in_progress
+ const hasPendingOperationsFromServer = useMemo(() => {
+ if (!messages || messages.length === 0) return false;
+ const pendingTypes = new Set([
+ "operation_pending",
+ "operation_in_progress",
+ "operation_started",
+ ]);
+ return messages.some((msg) => {
+ if (msg.role !== "tool" || !msg.content) return false;
+ try {
+ const content =
+ typeof msg.content === "string"
+ ? JSON.parse(msg.content)
+ : msg.content;
+ return pendingTypes.has(content?.type);
+ } catch {
+ return false;
+ }
+ });
+ }, [messages]);
+
+ // Track when server has acknowledged the pending operation
+ useEffect(() => {
+ if (hasPendingOperationsFromServer) {
+ hasSeenServerPendingRef.current = true;
+ }
+ }, [hasPendingOperationsFromServer]);
+
+ // Combined: poll if server has pending ops OR if we received operation_started via SSE
+ const hasPendingOperations = hasPendingOperationsFromServer || forcePolling;
+
+ // Clear forcePolling only after server has acknowledged AND completed the operation
+ useEffect(() => {
+ if (
+ forcePolling &&
+ !hasPendingOperationsFromServer &&
+ hasSeenServerPendingRef.current
+ ) {
+ // Server acknowledged the operation and it's now complete
+ setForcePolling(false);
+ hasSeenServerPendingRef.current = false;
+ }
+ }, [forcePolling, hasPendingOperationsFromServer]);
+
+ // Function to trigger polling (called when operation_started is received via SSE)
+ function startPollingForOperation() {
+ setForcePolling(true);
+ hasSeenServerPendingRef.current = false; // Reset for new operation
+ }
+
+ // Refresh sessions list when a pending operation completes
+ // (hasPendingOperations transitions from true to false)
+ const prevHasPendingOperationsRef = useRef(hasPendingOperations);
+ useEffect(
+ function refreshSessionsListOnOperationComplete() {
+ const wasHasPending = prevHasPendingOperationsRef.current;
+ prevHasPendingOperationsRef.current = hasPendingOperations;
+
+ // Only invalidate when transitioning from pending to not pending
+ if (wasHasPending && !hasPendingOperations && sessionId) {
+ queryClient.invalidateQueries({
+ queryKey: getGetV2ListSessionsQueryKey(),
+ });
+ }
+ },
+ [hasPendingOperations, sessionId, queryClient],
+ );
+
+ // Poll for updates when there are pending operations
+ // Backoff: 2s, 4s, 6s, 8s, 10s, ... up to 30s max
+ const pollAttemptRef = useRef(0);
+ const hasPendingOperationsRef = useRef(hasPendingOperations);
+ hasPendingOperationsRef.current = hasPendingOperations;
+
+ useEffect(
+ function pollForPendingOperations() {
+ if (!sessionId || !hasPendingOperations) {
+ pollAttemptRef.current = 0;
+ return;
+ }
+
+ let cancelled = false;
+ let timeoutId: ReturnType | null = null;
+
+ function schedule() {
+ // 2s, 4s, 6s, 8s, 10s, ... 30s (max)
+ const delay = Math.min((pollAttemptRef.current + 1) * 2000, 30000);
+ timeoutId = setTimeout(async () => {
+ if (cancelled) return;
+ pollAttemptRef.current += 1;
+ try {
+ await refetch();
+ } catch (err) {
+ console.error("[useChatSession] Poll failed:", err);
+ } finally {
+ if (!cancelled && hasPendingOperationsRef.current) {
+ schedule();
+ }
+ }
+ }, delay);
+ }
+
+ schedule();
+
+ return () => {
+ cancelled = true;
+ if (timeoutId) clearTimeout(timeoutId);
+ };
+ },
+ [sessionId, hasPendingOperations, refetch],
+ );
+
async function createSession() {
try {
setError(null);
@@ -227,11 +348,13 @@ export function useChatSession({
isCreating,
error,
isSessionNotFound: isNotFoundError(loadError),
+ hasPendingOperations,
createSession,
loadSession,
refreshSession,
claimSession,
clearSession,
+ startPollingForOperation,
};
}
diff --git a/autogpt_platform/frontend/src/components/contextual/Chat/useChatStream.ts b/autogpt_platform/frontend/src/components/contextual/Chat/useChatStream.ts
index 903c19cd30..5a9f637457 100644
--- a/autogpt_platform/frontend/src/components/contextual/Chat/useChatStream.ts
+++ b/autogpt_platform/frontend/src/components/contextual/Chat/useChatStream.ts
@@ -1,543 +1,110 @@
-import type { ToolArguments, ToolResult } from "@/types/chat";
-import { useCallback, useEffect, useRef, useState } from "react";
+"use client";
+
+import { useEffect, useRef, useState } from "react";
import { toast } from "sonner";
+import { useChatStore } from "./chat-store";
+import type { StreamChunk } from "./chat-types";
-const MAX_RETRIES = 3;
-const INITIAL_RETRY_DELAY = 1000;
-
-export interface StreamChunk {
- type:
- | "text_chunk"
- | "text_ended"
- | "tool_call"
- | "tool_call_start"
- | "tool_response"
- | "login_needed"
- | "need_login"
- | "credentials_needed"
- | "error"
- | "usage"
- | "stream_end";
- timestamp?: string;
- content?: string;
- message?: string;
- code?: string;
- details?: Record;
- tool_id?: string;
- tool_name?: string;
- arguments?: ToolArguments;
- result?: ToolResult;
- success?: boolean;
- idx?: number;
- session_id?: string;
- agent_info?: {
- graph_id: string;
- name: string;
- trigger_type: string;
- };
- provider?: string;
- provider_name?: string;
- credential_type?: string;
- scopes?: string[];
- title?: string;
- [key: string]: unknown;
-}
-
-type VercelStreamChunk =
- | { type: "start"; messageId: string }
- | { type: "finish" }
- | { type: "text-start"; id: string }
- | { type: "text-delta"; id: string; delta: string }
- | { type: "text-end"; id: string }
- | { type: "tool-input-start"; toolCallId: string; toolName: string }
- | {
- type: "tool-input-available";
- toolCallId: string;
- toolName: string;
- input: ToolArguments;
- }
- | {
- type: "tool-output-available";
- toolCallId: string;
- toolName?: string;
- output: ToolResult;
- success?: boolean;
- }
- | {
- type: "usage";
- promptTokens: number;
- completionTokens: number;
- totalTokens: number;
- }
- | {
- type: "error";
- errorText: string;
- code?: string;
- details?: Record;
- };
-
-const LEGACY_STREAM_TYPES = new Set([
- "text_chunk",
- "text_ended",
- "tool_call",
- "tool_call_start",
- "tool_response",
- "login_needed",
- "need_login",
- "credentials_needed",
- "error",
- "usage",
- "stream_end",
-]);
-
-function isLegacyStreamChunk(
- chunk: StreamChunk | VercelStreamChunk,
-): chunk is StreamChunk {
- return LEGACY_STREAM_TYPES.has(chunk.type as StreamChunk["type"]);
-}
-
-function normalizeStreamChunk(
- chunk: StreamChunk | VercelStreamChunk,
-): StreamChunk | null {
- if (isLegacyStreamChunk(chunk)) {
- return chunk;
- }
- switch (chunk.type) {
- case "text-delta":
- return { type: "text_chunk", content: chunk.delta };
- case "text-end":
- return { type: "text_ended" };
- case "tool-input-available":
- return {
- type: "tool_call_start",
- tool_id: chunk.toolCallId,
- tool_name: chunk.toolName,
- arguments: chunk.input,
- };
- case "tool-output-available":
- return {
- type: "tool_response",
- tool_id: chunk.toolCallId,
- tool_name: chunk.toolName,
- result: chunk.output,
- success: chunk.success ?? true,
- };
- case "usage":
- return {
- type: "usage",
- promptTokens: chunk.promptTokens,
- completionTokens: chunk.completionTokens,
- totalTokens: chunk.totalTokens,
- };
- case "error":
- return {
- type: "error",
- message: chunk.errorText,
- code: chunk.code,
- details: chunk.details,
- };
- case "finish":
- return { type: "stream_end" };
- case "start":
- case "text-start":
- return null;
- case "tool-input-start":
- const toolInputStart = chunk as Extract<
- VercelStreamChunk,
- { type: "tool-input-start" }
- >;
- return {
- type: "tool_call_start",
- tool_id: toolInputStart.toolCallId,
- tool_name: toolInputStart.toolName,
- arguments: {},
- };
- }
-}
+export type { StreamChunk } from "./chat-types";
export function useChatStream() {
const [isStreaming, setIsStreaming] = useState(false);
const [error, setError] = useState(null);
- const retryCountRef = useRef(0);
- const retryTimeoutRef = useRef(null);
- const abortControllerRef = useRef(null);
const currentSessionIdRef = useRef(null);
- const requestStartTimeRef = useRef(null);
-
- const stopStreaming = useCallback(
- (sessionId?: string, force: boolean = false) => {
- console.log("[useChatStream] stopStreaming called", {
- hasAbortController: !!abortControllerRef.current,
- isAborted: abortControllerRef.current?.signal.aborted,
- currentSessionId: currentSessionIdRef.current,
- requestedSessionId: sessionId,
- requestStartTime: requestStartTimeRef.current,
- timeSinceStart: requestStartTimeRef.current
- ? Date.now() - requestStartTimeRef.current
- : null,
- force,
- stack: new Error().stack,
- });
-
- if (
- sessionId &&
- currentSessionIdRef.current &&
- currentSessionIdRef.current !== sessionId
- ) {
- console.log(
- "[useChatStream] Session changed, aborting previous stream",
- {
- oldSessionId: currentSessionIdRef.current,
- newSessionId: sessionId,
- },
- );
- }
-
- const controller = abortControllerRef.current;
- if (controller) {
- const timeSinceStart = requestStartTimeRef.current
- ? Date.now() - requestStartTimeRef.current
- : null;
-
- if (!force && timeSinceStart !== null && timeSinceStart < 100) {
- console.log(
- "[useChatStream] Request just started (<100ms), skipping abort to prevent race condition",
- {
- timeSinceStart,
- },
- );
- return;
- }
-
- try {
- const signal = controller.signal;
-
- if (
- signal &&
- typeof signal.aborted === "boolean" &&
- !signal.aborted
- ) {
- console.log("[useChatStream] Aborting stream");
- controller.abort();
- } else {
- console.log(
- "[useChatStream] Stream already aborted or signal invalid",
- );
- }
- } catch (error) {
- if (error instanceof Error && error.name === "AbortError") {
- console.log(
- "[useChatStream] AbortError caught (expected during cleanup)",
- );
- } else {
- console.warn("[useChatStream] Error aborting stream:", error);
- }
- } finally {
- abortControllerRef.current = null;
- requestStartTimeRef.current = null;
- }
- }
- if (retryTimeoutRef.current) {
- clearTimeout(retryTimeoutRef.current);
- retryTimeoutRef.current = null;
- }
- setIsStreaming(false);
- },
- [],
+ const onChunkCallbackRef = useRef<((chunk: StreamChunk) => void) | null>(
+ null,
);
+ const stopStream = useChatStore((s) => s.stopStream);
+ const unregisterActiveSession = useChatStore(
+ (s) => s.unregisterActiveSession,
+ );
+ const isSessionActive = useChatStore((s) => s.isSessionActive);
+ const onStreamComplete = useChatStore((s) => s.onStreamComplete);
+ const getCompletedStream = useChatStore((s) => s.getCompletedStream);
+ const registerActiveSession = useChatStore((s) => s.registerActiveSession);
+ const startStream = useChatStore((s) => s.startStream);
+ const getStreamStatus = useChatStore((s) => s.getStreamStatus);
+
+ function stopStreaming(sessionId?: string) {
+ const targetSession = sessionId || currentSessionIdRef.current;
+ if (targetSession) {
+ stopStream(targetSession);
+ unregisterActiveSession(targetSession);
+ }
+ setIsStreaming(false);
+ }
+
useEffect(() => {
- console.log("[useChatStream] Component mounted");
- return () => {
- const sessionIdAtUnmount = currentSessionIdRef.current;
- console.log(
- "[useChatStream] Component unmounting, calling stopStreaming",
- {
- sessionIdAtUnmount,
- },
- );
- stopStreaming(undefined, false);
+ return function cleanup() {
+ const sessionId = currentSessionIdRef.current;
+ if (sessionId && !isSessionActive(sessionId)) {
+ stopStream(sessionId);
+ }
currentSessionIdRef.current = null;
+ onChunkCallbackRef.current = null;
};
- }, [stopStreaming]);
+ }, []);
- const sendMessage = useCallback(
- async (
- sessionId: string,
- message: string,
- onChunk: (chunk: StreamChunk) => void,
- isUserMessage: boolean = true,
- context?: { url: string; content: string },
- isRetry: boolean = false,
- ) => {
- console.log("[useChatStream] sendMessage called", {
- sessionId,
- message: message.substring(0, 50),
- isUserMessage,
- isRetry,
- stack: new Error().stack,
- });
+ useEffect(() => {
+ const unsubscribe = onStreamComplete(
+ function handleStreamComplete(completedSessionId) {
+ if (completedSessionId !== currentSessionIdRef.current) return;
- const previousSessionId = currentSessionIdRef.current;
- stopStreaming(sessionId, true);
- currentSessionIdRef.current = sessionId;
-
- const abortController = new AbortController();
- abortControllerRef.current = abortController;
- requestStartTimeRef.current = Date.now();
- console.log("[useChatStream] Created new AbortController", {
- sessionId,
- previousSessionId,
- requestStartTime: requestStartTimeRef.current,
- });
-
- if (abortController.signal.aborted) {
- console.warn(
- "[useChatStream] AbortController was aborted before request started",
- );
- requestStartTimeRef.current = null;
- return Promise.reject(new Error("Request aborted"));
- }
-
- if (!isRetry) {
- retryCountRef.current = 0;
- }
- setIsStreaming(true);
- setError(null);
-
- try {
- const url = `/api/chat/sessions/${sessionId}/stream`;
- const body = JSON.stringify({
- message,
- is_user_message: isUserMessage,
- context: context || null,
- });
-
- const response = await fetch(url, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Accept: "text/event-stream",
- },
- body,
- signal: abortController.signal,
- });
-
- console.info("[useChatStream] Stream response", {
- sessionId,
- status: response.status,
- ok: response.ok,
- contentType: response.headers.get("content-type"),
- });
-
- if (!response.ok) {
- const errorText = await response.text();
- console.warn("[useChatStream] Stream response error", {
- sessionId,
- status: response.status,
- errorText,
- });
- throw new Error(errorText || `HTTP ${response.status}`);
- }
-
- if (!response.body) {
- console.warn("[useChatStream] Response body is null", { sessionId });
- throw new Error("Response body is null");
- }
-
- const reader = response.body.getReader();
- const decoder = new TextDecoder();
- let buffer = "";
- let receivedChunkCount = 0;
- let firstChunkAt: number | null = null;
- let loggedLineCount = 0;
-
- return new Promise((resolve, reject) => {
- let didDispatchStreamEnd = false;
-
- function dispatchStreamEnd() {
- if (didDispatchStreamEnd) return;
- didDispatchStreamEnd = true;
- onChunk({ type: "stream_end" });
- }
-
- const cleanup = () => {
- reader.cancel().catch(() => {
- // Ignore cancel errors
- });
- };
-
- async function readStream() {
- try {
- while (true) {
- const { done, value } = await reader.read();
-
- if (done) {
- cleanup();
- console.info("[useChatStream] Stream closed", {
- sessionId,
- receivedChunkCount,
- timeSinceStart: requestStartTimeRef.current
- ? Date.now() - requestStartTimeRef.current
- : null,
- });
- dispatchStreamEnd();
- retryCountRef.current = 0;
- stopStreaming();
- resolve();
- return;
- }
-
- buffer += decoder.decode(value, { stream: true });
- const lines = buffer.split("\n");
- buffer = lines.pop() || "";
-
- for (const line of lines) {
- if (line.startsWith("data: ")) {
- const data = line.slice(6);
- if (loggedLineCount < 3) {
- console.info("[useChatStream] Raw stream line", {
- sessionId,
- data:
- data.length > 300 ? `${data.slice(0, 300)}...` : data,
- });
- loggedLineCount += 1;
- }
- if (data === "[DONE]") {
- cleanup();
- console.info("[useChatStream] Stream done marker", {
- sessionId,
- receivedChunkCount,
- timeSinceStart: requestStartTimeRef.current
- ? Date.now() - requestStartTimeRef.current
- : null,
- });
- dispatchStreamEnd();
- retryCountRef.current = 0;
- stopStreaming();
- resolve();
- return;
- }
-
- try {
- const rawChunk = JSON.parse(data) as
- | StreamChunk
- | VercelStreamChunk;
- const chunk = normalizeStreamChunk(rawChunk);
- if (!chunk) {
- continue;
- }
-
- if (!firstChunkAt) {
- firstChunkAt = Date.now();
- console.info("[useChatStream] First stream chunk", {
- sessionId,
- chunkType: chunk.type,
- timeSinceStart: requestStartTimeRef.current
- ? firstChunkAt - requestStartTimeRef.current
- : null,
- });
- }
- receivedChunkCount += 1;
-
- // Call the chunk handler
- onChunk(chunk);
-
- // Handle stream lifecycle
- if (chunk.type === "stream_end") {
- didDispatchStreamEnd = true;
- cleanup();
- console.info("[useChatStream] Stream end chunk", {
- sessionId,
- receivedChunkCount,
- timeSinceStart: requestStartTimeRef.current
- ? Date.now() - requestStartTimeRef.current
- : null,
- });
- retryCountRef.current = 0;
- stopStreaming();
- resolve();
- return;
- } else if (chunk.type === "error") {
- cleanup();
- reject(
- new Error(
- chunk.message || chunk.content || "Stream error",
- ),
- );
- return;
- }
- } catch (err) {
- // Skip invalid JSON lines
- console.warn("Failed to parse SSE chunk:", err, data);
- }
- }
- }
- }
- } catch (err) {
- if (err instanceof Error && err.name === "AbortError") {
- cleanup();
- dispatchStreamEnd();
- stopStreaming();
- resolve();
- return;
- }
-
- const streamError =
- err instanceof Error ? err : new Error("Failed to read stream");
-
- if (retryCountRef.current < MAX_RETRIES) {
- retryCountRef.current += 1;
- const retryDelay =
- INITIAL_RETRY_DELAY * Math.pow(2, retryCountRef.current - 1);
-
- toast.info("Connection interrupted", {
- description: `Retrying in ${retryDelay / 1000} seconds...`,
- });
-
- retryTimeoutRef.current = setTimeout(() => {
- sendMessage(
- sessionId,
- message,
- onChunk,
- isUserMessage,
- context,
- true,
- ).catch((_err) => {
- // Retry failed
- });
- }, retryDelay);
- } else {
- setError(streamError);
- toast.error("Connection Failed", {
- description:
- "Unable to connect to chat service. Please try again.",
- });
- cleanup();
- dispatchStreamEnd();
- retryCountRef.current = 0;
- stopStreaming();
- reject(streamError);
- }
- }
- }
-
- readStream();
- });
- } catch (err) {
- if (err instanceof Error && err.name === "AbortError") {
- setIsStreaming(false);
- return Promise.resolve();
- }
- const streamError =
- err instanceof Error ? err : new Error("Failed to start stream");
- setError(streamError);
setIsStreaming(false);
- throw streamError;
+ const completed = getCompletedStream(completedSessionId);
+ if (completed?.error) {
+ setError(completed.error);
+ }
+ unregisterActiveSession(completedSessionId);
+ },
+ );
+
+ return unsubscribe;
+ }, []);
+
+ async function sendMessage(
+ sessionId: string,
+ message: string,
+ onChunk: (chunk: StreamChunk) => void,
+ isUserMessage: boolean = true,
+ context?: { url: string; content: string },
+ ) {
+ const previousSessionId = currentSessionIdRef.current;
+ if (previousSessionId && previousSessionId !== sessionId) {
+ stopStreaming(previousSessionId);
+ }
+
+ currentSessionIdRef.current = sessionId;
+ onChunkCallbackRef.current = onChunk;
+ setIsStreaming(true);
+ setError(null);
+
+ registerActiveSession(sessionId);
+
+ try {
+ await startStream(sessionId, message, isUserMessage, context, onChunk);
+
+ const status = getStreamStatus(sessionId);
+ if (status === "error") {
+ const completed = getCompletedStream(sessionId);
+ if (completed?.error) {
+ setError(completed.error);
+ toast.error("Connection Failed", {
+ description: "Unable to connect to chat service. Please try again.",
+ });
+ throw completed.error;
+ }
}
- },
- [stopStreaming],
- );
+ } catch (err) {
+ const streamError =
+ err instanceof Error ? err : new Error("Failed to start stream");
+ setError(streamError);
+ throw streamError;
+ } finally {
+ setIsStreaming(false);
+ }
+ }
return {
isStreaming,
diff --git a/autogpt_platform/frontend/src/components/layout/Navbar/components/Wallet/Wallet.tsx b/autogpt_platform/frontend/src/components/layout/Navbar/components/Wallet/Wallet.tsx
index 0a3c7de6c8..4a25c84f92 100644
--- a/autogpt_platform/frontend/src/components/layout/Navbar/components/Wallet/Wallet.tsx
+++ b/autogpt_platform/frontend/src/components/layout/Navbar/components/Wallet/Wallet.tsx
@@ -255,13 +255,18 @@ export function Wallet() {
(notification: WebSocketNotification) => {
if (
notification.type !== "onboarding" ||
- notification.event !== "step_completed" ||
- !walletRef.current
+ notification.event !== "step_completed"
) {
return;
}
- // Only trigger confetti for tasks that are in groups
+ // Always refresh credits when any onboarding step completes
+ fetchCredits();
+
+ // Only trigger confetti for tasks that are in displayed groups
+ if (!walletRef.current) {
+ return;
+ }
const taskIds = groups
.flatMap((group) => group.tasks)
.map((task) => task.id);
@@ -274,7 +279,6 @@ export function Wallet() {
return;
}
- fetchCredits();
party.confetti(walletRef.current, {
count: 30,
spread: 120,
@@ -284,7 +288,7 @@ export function Wallet() {
modules: [fadeOut],
});
},
- [fetchCredits, fadeOut],
+ [fetchCredits, fadeOut, groups],
);
// WebSocket setup for onboarding notifications
diff --git a/autogpt_platform/frontend/src/components/organisms/FloatingReviewsPanel/FloatingReviewsPanel.tsx b/autogpt_platform/frontend/src/components/organisms/FloatingReviewsPanel/FloatingReviewsPanel.tsx
index 2b04c0ed9a..4805508054 100644
--- a/autogpt_platform/frontend/src/components/organisms/FloatingReviewsPanel/FloatingReviewsPanel.tsx
+++ b/autogpt_platform/frontend/src/components/organisms/FloatingReviewsPanel/FloatingReviewsPanel.tsx
@@ -31,6 +31,29 @@ export function FloatingReviewsPanel({
query: {
enabled: !!(graphId && executionId),
select: okData,
+ // Poll while execution is in progress to detect status changes
+ refetchInterval: (q) => {
+ // Note: refetchInterval callback receives raw data before select transform
+ const rawData = q.state.data as
+ | { status: number; data?: { status?: string } }
+ | undefined;
+ if (rawData?.status !== 200) return false;
+
+ const status = rawData?.data?.status;
+ if (!status) return false;
+
+ // Poll every 2 seconds while running or in review
+ if (
+ status === AgentExecutionStatus.RUNNING ||
+ status === AgentExecutionStatus.QUEUED ||
+ status === AgentExecutionStatus.INCOMPLETE ||
+ status === AgentExecutionStatus.REVIEW
+ ) {
+ return 2000;
+ }
+ return false;
+ },
+ refetchIntervalInBackground: true,
},
},
);
@@ -40,28 +63,47 @@ export function FloatingReviewsPanel({
useShallow((state) => state.graphExecutionStatus),
);
+ // Determine if we should poll for pending reviews
+ const isInReviewStatus =
+ executionDetails?.status === AgentExecutionStatus.REVIEW ||
+ graphExecutionStatus === AgentExecutionStatus.REVIEW;
+
const { pendingReviews, isLoading, refetch } = usePendingReviewsForExecution(
executionId || "",
+ {
+ enabled: !!executionId,
+ // Poll every 2 seconds when in REVIEW status to catch new reviews
+ refetchInterval: isInReviewStatus ? 2000 : false,
+ },
);
+ // Refetch pending reviews when execution status changes
useEffect(() => {
- if (executionId) {
+ if (executionId && executionDetails?.status) {
refetch();
}
}, [executionDetails?.status, executionId, refetch]);
- // Refetch when graph execution status changes to REVIEW
- useEffect(() => {
- if (graphExecutionStatus === AgentExecutionStatus.REVIEW && executionId) {
- refetch();
- }
- }, [graphExecutionStatus, executionId, refetch]);
+ // Hide panel if:
+ // 1. No execution ID
+ // 2. No pending reviews and not in REVIEW status
+ // 3. Execution is RUNNING or QUEUED (hasn't paused for review yet)
+ if (!executionId) {
+ return null;
+ }
if (
- !executionId ||
- (!isLoading &&
- pendingReviews.length === 0 &&
- executionDetails?.status !== AgentExecutionStatus.REVIEW)
+ !isLoading &&
+ pendingReviews.length === 0 &&
+ executionDetails?.status !== AgentExecutionStatus.REVIEW
+ ) {
+ return null;
+ }
+
+ // Don't show panel while execution is still running/queued (not paused for review)
+ if (
+ executionDetails?.status === AgentExecutionStatus.RUNNING ||
+ executionDetails?.status === AgentExecutionStatus.QUEUED
) {
return null;
}
diff --git a/autogpt_platform/frontend/src/components/organisms/PendingReviewCard/PendingReviewCard.tsx b/autogpt_platform/frontend/src/components/organisms/PendingReviewCard/PendingReviewCard.tsx
index 3ac636060c..bd456ce771 100644
--- a/autogpt_platform/frontend/src/components/organisms/PendingReviewCard/PendingReviewCard.tsx
+++ b/autogpt_platform/frontend/src/components/organisms/PendingReviewCard/PendingReviewCard.tsx
@@ -1,10 +1,8 @@
import { PendingHumanReviewModel } from "@/app/api/__generated__/models/pendingHumanReviewModel";
import { Text } from "@/components/atoms/Text/Text";
-import { Button } from "@/components/atoms/Button/Button";
import { Input } from "@/components/atoms/Input/Input";
import { Switch } from "@/components/atoms/Switch/Switch";
-import { TrashIcon, EyeSlashIcon } from "@phosphor-icons/react";
-import { useState } from "react";
+import { useEffect, useState } from "react";
interface StructuredReviewPayload {
data: unknown;
@@ -40,37 +38,49 @@ function extractReviewData(payload: unknown): {
interface PendingReviewCardProps {
review: PendingHumanReviewModel;
onReviewDataChange: (nodeExecId: string, data: string) => void;
- reviewMessage?: string;
- onReviewMessageChange?: (nodeExecId: string, message: string) => void;
- isDisabled?: boolean;
- onToggleDisabled?: (nodeExecId: string) => void;
+ autoApproveFuture?: boolean;
+ onAutoApproveFutureChange?: (nodeExecId: string, enabled: boolean) => void;
+ externalDataValue?: string;
+ showAutoApprove?: boolean;
+ nodeId?: string;
}
export function PendingReviewCard({
review,
onReviewDataChange,
- reviewMessage = "",
- onReviewMessageChange,
- isDisabled = false,
- onToggleDisabled,
+ autoApproveFuture = false,
+ onAutoApproveFutureChange,
+ externalDataValue,
+ showAutoApprove = true,
+ nodeId,
}: PendingReviewCardProps) {
const extractedData = extractReviewData(review.payload);
const isDataEditable = review.editable;
- const instructions = extractedData.instructions || review.instructions;
+
+ let instructions = review.instructions;
+
+ const isHITLBlock = instructions && !instructions.includes("Block");
+
+ if (instructions && !isHITLBlock) {
+ instructions = undefined;
+ }
+
const [currentData, setCurrentData] = useState(extractedData.data);
+ useEffect(() => {
+ if (externalDataValue !== undefined) {
+ try {
+ const parsedData = JSON.parse(externalDataValue);
+ setCurrentData(parsedData);
+ } catch {}
+ }
+ }, [externalDataValue]);
+
const handleDataChange = (newValue: unknown) => {
setCurrentData(newValue);
onReviewDataChange(review.node_exec_id, JSON.stringify(newValue, null, 2));
};
- const handleMessageChange = (newMessage: string) => {
- onReviewMessageChange?.(review.node_exec_id, newMessage);
- };
-
- // Show simplified view when no toggle functionality is provided (Screenshot 1 mode)
- const showSimplified = !onToggleDisabled;
-
const renderDataInput = () => {
const data = currentData;
@@ -137,97 +147,59 @@ export function PendingReviewCard({
}
};
- // Helper function to get proper field label
- const getFieldLabel = (instructions?: string) => {
- if (instructions)
- return instructions.charAt(0).toUpperCase() + instructions.slice(1);
- return "Data to Review";
+ const getShortenedNodeId = (id: string) => {
+ if (id.length <= 8) return id;
+ return `${id.slice(0, 4)}...${id.slice(-4)}`;
};
- // Use the existing HITL review interface
return (
- {!showSimplified && (
-
-
- {isDisabled && (
-
- This item will be rejected
-
- )}
+ {nodeId && (
+
+ Node #{getShortenedNodeId(nodeId)}
+
+ )}
+
+
+ {instructions && (
+
+ {instructions}
+
+ )}
+
+ {isDataEditable && !autoApproveFuture ? (
+ renderDataInput()
+ ) : (
+
+
+ {JSON.stringify(currentData, null, 2)}
+
-
-
- )}
+ )}
+
- {/* Show instructions as field label */}
- {instructions && (
-
-
- {getFieldLabel(instructions)}
-
- {isDataEditable && !isDisabled ? (
- renderDataInput()
- ) : (
-
-
- {JSON.stringify(currentData, null, 2)}
-
-
+ {/* Auto-approve toggle for this review */}
+ {showAutoApprove && onAutoApproveFutureChange && (
+
+
+
+ onAutoApproveFutureChange(review.node_exec_id, enabled)
+ }
+ />
+
+ Auto-approve future executions of this block
+
+
+ {autoApproveFuture && (
+
+ Original data will be used for this and all future reviews from
+ this block.
+
)}
)}
-
- {/* If no instructions, show data directly */}
- {!instructions && (
-
-
- Data to Review
- {!isDataEditable && (
-
- (Read-only)
-
- )}
-
- {isDataEditable && !isDisabled ? (
- renderDataInput()
- ) : (
-
-
- {JSON.stringify(currentData, null, 2)}
-
-
- )}
-
- )}
-
- {!showSimplified && isDisabled && (
-
-
- Rejection Reason (Optional):
-
- handleMessageChange(e.target.value)}
- placeholder="Add any notes about why you're rejecting this..."
- />
-
- )}
);
}
diff --git a/autogpt_platform/frontend/src/components/organisms/PendingReviewsList/PendingReviewsList.tsx b/autogpt_platform/frontend/src/components/organisms/PendingReviewsList/PendingReviewsList.tsx
index 3253b0ee6d..5adb3919b6 100644
--- a/autogpt_platform/frontend/src/components/organisms/PendingReviewsList/PendingReviewsList.tsx
+++ b/autogpt_platform/frontend/src/components/organisms/PendingReviewsList/PendingReviewsList.tsx
@@ -1,10 +1,16 @@
-import { useState } from "react";
+import { useMemo, useState } from "react";
import { PendingHumanReviewModel } from "@/app/api/__generated__/models/pendingHumanReviewModel";
import { PendingReviewCard } from "@/components/organisms/PendingReviewCard/PendingReviewCard";
import { Text } from "@/components/atoms/Text/Text";
import { Button } from "@/components/atoms/Button/Button";
+import { Switch } from "@/components/atoms/Switch/Switch";
import { useToast } from "@/components/molecules/Toast/use-toast";
-import { ClockIcon, WarningIcon } from "@phosphor-icons/react";
+import {
+ ClockIcon,
+ WarningIcon,
+ CaretDownIcon,
+ CaretRightIcon,
+} from "@phosphor-icons/react";
import { usePostV2ProcessReviewAction } from "@/app/api/__generated__/endpoints/executions/executions";
interface PendingReviewsListProps {
@@ -32,16 +38,34 @@ export function PendingReviewsList({
},
);
- const [reviewMessageMap, setReviewMessageMap] = useState<
- Record
- >({});
-
const [pendingAction, setPendingAction] = useState<
"approve" | "reject" | null
>(null);
+ const [autoApproveFutureMap, setAutoApproveFutureMap] = useState<
+ Record
+ >({});
+
+ const [collapsedGroups, setCollapsedGroups] = useState<
+ Record
+ >({});
+
const { toast } = useToast();
+ const groupedReviews = useMemo(() => {
+ return reviews.reduce(
+ (acc, review) => {
+ const nodeId = review.node_id || "unknown";
+ if (!acc[nodeId]) {
+ acc[nodeId] = [];
+ }
+ acc[nodeId].push(review);
+ return acc;
+ },
+ {} as Record,
+ );
+ }, [reviews]);
+
const reviewActionMutation = usePostV2ProcessReviewAction({
mutation: {
onSuccess: (res) => {
@@ -88,8 +112,33 @@ export function PendingReviewsList({
setReviewDataMap((prev) => ({ ...prev, [nodeExecId]: data }));
}
- function handleReviewMessageChange(nodeExecId: string, message: string) {
- setReviewMessageMap((prev) => ({ ...prev, [nodeExecId]: message }));
+ function handleAutoApproveFutureToggle(nodeId: string, enabled: boolean) {
+ setAutoApproveFutureMap((prev) => ({
+ ...prev,
+ [nodeId]: enabled,
+ }));
+
+ if (enabled) {
+ const nodeReviews = groupedReviews[nodeId] || [];
+ setReviewDataMap((prev) => {
+ const updated = { ...prev };
+ nodeReviews.forEach((review) => {
+ updated[review.node_exec_id] = JSON.stringify(
+ review.payload,
+ null,
+ 2,
+ );
+ });
+ return updated;
+ });
+ }
+ }
+
+ function toggleGroupCollapse(nodeId: string) {
+ setCollapsedGroups((prev) => ({
+ ...prev,
+ [nodeId]: !prev[nodeId],
+ }));
}
function processReviews(approved: boolean) {
@@ -107,22 +156,25 @@ export function PendingReviewsList({
for (const review of reviews) {
const reviewData = reviewDataMap[review.node_exec_id];
- const reviewMessage = reviewMessageMap[review.node_exec_id];
+ const autoApproveThisNode = autoApproveFutureMap[review.node_id || ""];
- let parsedData: any = review.payload; // Default to original payload
+ let parsedData: any = undefined;
- // Parse edited data if available and editable
- if (review.editable && reviewData) {
- try {
- parsedData = JSON.parse(reviewData);
- } catch (error) {
- toast({
- title: "Invalid JSON",
- description: `Please fix the JSON format in review for node ${review.node_exec_id}: ${error instanceof Error ? error.message : "Invalid syntax"}`,
- variant: "destructive",
- });
- setPendingAction(null);
- return;
+ if (!autoApproveThisNode) {
+ if (review.editable && reviewData) {
+ try {
+ parsedData = JSON.parse(reviewData);
+ } catch (error) {
+ toast({
+ title: "Invalid JSON",
+ description: `Please fix the JSON format in review for node ${review.node_exec_id}: ${error instanceof Error ? error.message : "Invalid syntax"}`,
+ variant: "destructive",
+ });
+ setPendingAction(null);
+ return;
+ }
+ } else {
+ parsedData = review.payload;
}
}
@@ -130,7 +182,7 @@ export function PendingReviewsList({
node_exec_id: review.node_exec_id,
approved,
reviewed_data: parsedData,
- message: reviewMessage || undefined,
+ auto_approve_future: autoApproveThisNode && approved,
});
}
@@ -158,7 +210,6 @@ export function PendingReviewsList({
return (
- {/* Warning Box Header */}
- {reviews.map((review) => (
-
- ))}
+ {Object.entries(groupedReviews).map(([nodeId, nodeReviews]) => {
+ const isCollapsed = collapsedGroups[nodeId] ?? nodeReviews.length > 1;
+ const reviewCount = nodeReviews.length;
+
+ const firstReview = nodeReviews[0];
+ const blockName = firstReview?.instructions;
+ const reviewTitle = `Review required for ${blockName}`;
+
+ const getShortenedNodeId = (id: string) => {
+ if (id.length <= 8) return id;
+ return `${id.slice(0, 4)}...${id.slice(-4)}`;
+ };
+
+ return (
+
+
+
+ {!isCollapsed && (
+
+ {nodeReviews.map((review) => (
+
+ ))}
+
+
+
+ handleAutoApproveFutureToggle(nodeId, enabled)
+ }
+ />
+
+ Auto-approve future executions of this node
+
+
+
+ )}
+
+ );
+ })}
-
-
- Note: Changes you make here apply only to this task
-
-
-
+
+
+
+
+ You can turn auto-approval on or off using the toggle above for each
+ node.
+
);
diff --git a/autogpt_platform/frontend/src/hooks/usePendingReviews.ts b/autogpt_platform/frontend/src/hooks/usePendingReviews.ts
index 8257814fcf..b9d7d711a1 100644
--- a/autogpt_platform/frontend/src/hooks/usePendingReviews.ts
+++ b/autogpt_platform/frontend/src/hooks/usePendingReviews.ts
@@ -15,8 +15,22 @@ export function usePendingReviews() {
};
}
-export function usePendingReviewsForExecution(graphExecId: string) {
- const query = useGetV2GetPendingReviewsForExecution(graphExecId);
+interface UsePendingReviewsForExecutionOptions {
+ enabled?: boolean;
+ refetchInterval?: number | false;
+}
+
+export function usePendingReviewsForExecution(
+ graphExecId: string,
+ options?: UsePendingReviewsForExecutionOptions,
+) {
+ const query = useGetV2GetPendingReviewsForExecution(graphExecId, {
+ query: {
+ enabled: options?.enabled ?? !!graphExecId,
+ refetchInterval: options?.refetchInterval,
+ refetchIntervalInBackground: !!options?.refetchInterval,
+ },
+ });
return {
pendingReviews: okData(query.data) || [],
diff --git a/autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts b/autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts
index 82c03bc9f1..74855f5e28 100644
--- a/autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts
+++ b/autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts
@@ -516,7 +516,7 @@ export type GraphValidationErrorResponse = {
/* *** LIBRARY *** */
-/* Mirror of backend/server/v2/library/model.py:LibraryAgent */
+/* Mirror of backend/api/features/library/model.py:LibraryAgent */
export type LibraryAgent = {
id: LibraryAgentID;
graph_id: GraphID;
@@ -616,7 +616,7 @@ export enum LibraryAgentSortEnum {
/* *** CREDENTIALS *** */
-/* Mirror of backend/server/integrations/router.py:CredentialsMetaResponse */
+/* Mirror of backend/api/features/integrations/router.py:CredentialsMetaResponse */
export type CredentialsMetaResponse = {
id: string;
provider: CredentialsProviderName;
@@ -628,13 +628,13 @@ export type CredentialsMetaResponse = {
is_system?: boolean;
};
-/* Mirror of backend/server/integrations/router.py:CredentialsDeletionResponse */
+/* Mirror of backend/api/features/integrations/router.py:CredentialsDeletionResponse */
export type CredentialsDeleteResponse = {
deleted: true;
revoked: boolean | null;
};
-/* Mirror of backend/server/integrations/router.py:CredentialsDeletionNeedsConfirmationResponse */
+/* Mirror of backend/api/features/integrations/router.py:CredentialsDeletionNeedsConfirmationResponse */
export type CredentialsDeleteNeedConfirmationResponse = {
deleted: false;
need_confirmation: true;
@@ -888,7 +888,7 @@ export type Schedule = {
export type ScheduleID = Brand
;
-/* Mirror of backend/server/routers/v1.py:ScheduleCreationRequest */
+/* Mirror of backend/api/features/v1.py:ScheduleCreationRequest */
export type ScheduleCreatable = {
graph_id: GraphID;
graph_version: number;
@@ -1003,6 +1003,7 @@ export type OnboardingStep =
| "AGENT_INPUT"
| "CONGRATS"
// First Wins
+ | "VISIT_COPILOT"
| "GET_RESULTS"
| "MARKETPLACE_VISIT"
| "MARKETPLACE_ADD_AGENT"
diff --git a/autogpt_platform/frontend/src/providers/posthog/posthog-provider.tsx b/autogpt_platform/frontend/src/providers/posthog/posthog-provider.tsx
new file mode 100644
index 0000000000..674f6c55eb
--- /dev/null
+++ b/autogpt_platform/frontend/src/providers/posthog/posthog-provider.tsx
@@ -0,0 +1,72 @@
+"use client";
+
+import { useSupabase } from "@/lib/supabase/hooks/useSupabase";
+import { environment } from "@/services/environment";
+import { PostHogProvider as PHProvider } from "@posthog/react";
+import { usePathname, useSearchParams } from "next/navigation";
+import posthog from "posthog-js";
+import { ReactNode, useEffect, useRef } from "react";
+
+export function PostHogProvider({ children }: { children: ReactNode }) {
+ const isPostHogEnabled = environment.isPostHogEnabled();
+ const postHogCredentials = environment.getPostHogCredentials();
+
+ useEffect(() => {
+ if (postHogCredentials.key) {
+ posthog.init(postHogCredentials.key, {
+ api_host: postHogCredentials.host,
+ defaults: "2025-11-30",
+ capture_pageview: false,
+ capture_pageleave: true,
+ autocapture: true,
+ });
+ }
+ }, []);
+
+ if (!isPostHogEnabled) return <>{children}>;
+
+ return {children};
+}
+
+export function PostHogUserTracker() {
+ const { user, isUserLoading } = useSupabase();
+ const previousUserIdRef = useRef(null);
+ const isPostHogEnabled = environment.isPostHogEnabled();
+
+ useEffect(() => {
+ if (isUserLoading || !isPostHogEnabled) return;
+
+ if (user) {
+ if (previousUserIdRef.current !== user.id) {
+ posthog.identify(user.id, {
+ email: user.email,
+ ...(user.user_metadata?.name && { name: user.user_metadata.name }),
+ });
+ previousUserIdRef.current = user.id;
+ }
+ } else if (previousUserIdRef.current !== null) {
+ posthog.reset();
+ previousUserIdRef.current = null;
+ }
+ }, [user, isUserLoading, isPostHogEnabled]);
+
+ return null;
+}
+
+export function PostHogPageViewTracker() {
+ const pathname = usePathname();
+ const searchParams = useSearchParams();
+ const isPostHogEnabled = environment.isPostHogEnabled();
+
+ useEffect(() => {
+ if (pathname && isPostHogEnabled) {
+ let url = window.origin + pathname;
+ if (searchParams && searchParams.toString()) {
+ url = url + `?${searchParams.toString()}`;
+ }
+ posthog.capture("$pageview", { $current_url: url });
+ }
+ }, [pathname, searchParams, isPostHogEnabled]);
+
+ return null;
+}
diff --git a/autogpt_platform/frontend/src/services/environment/index.ts b/autogpt_platform/frontend/src/services/environment/index.ts
index cdd5b421b5..f19bc417e3 100644
--- a/autogpt_platform/frontend/src/services/environment/index.ts
+++ b/autogpt_platform/frontend/src/services/environment/index.ts
@@ -76,6 +76,13 @@ function getPreviewStealingDev() {
return branch;
}
+function getPostHogCredentials() {
+ return {
+ key: process.env.NEXT_PUBLIC_POSTHOG_KEY,
+ host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
+ };
+}
+
function isProductionBuild() {
return process.env.NODE_ENV === "production";
}
@@ -116,6 +123,13 @@ function areFeatureFlagsEnabled() {
return process.env.NEXT_PUBLIC_LAUNCHDARKLY_ENABLED === "enabled";
}
+function isPostHogEnabled() {
+ const inCloud = isCloud();
+ const key = process.env.NEXT_PUBLIC_POSTHOG_KEY;
+ const host = process.env.NEXT_PUBLIC_POSTHOG_HOST;
+ return inCloud && key && host;
+}
+
export const environment = {
// Generic
getEnvironmentStr,
@@ -128,6 +142,7 @@ export const environment = {
getSupabaseUrl,
getSupabaseAnonKey,
getPreviewStealingDev,
+ getPostHogCredentials,
// Assertions
isServerSide,
isClientSide,
@@ -138,5 +153,6 @@ export const environment = {
isCloud,
isLocal,
isVercelPreview,
+ isPostHogEnabled,
areFeatureFlagsEnabled,
};
diff --git a/autogpt_platform/frontend/src/services/network-status/NetworkStatusMonitor.tsx b/autogpt_platform/frontend/src/services/network-status/NetworkStatusMonitor.tsx
new file mode 100644
index 0000000000..7552bbf78c
--- /dev/null
+++ b/autogpt_platform/frontend/src/services/network-status/NetworkStatusMonitor.tsx
@@ -0,0 +1,8 @@
+"use client";
+
+import { useNetworkStatus } from "./useNetworkStatus";
+
+export function NetworkStatusMonitor() {
+ useNetworkStatus();
+ return null;
+}
diff --git a/autogpt_platform/frontend/src/services/network-status/useNetworkStatus.ts b/autogpt_platform/frontend/src/services/network-status/useNetworkStatus.ts
new file mode 100644
index 0000000000..472a6e0e90
--- /dev/null
+++ b/autogpt_platform/frontend/src/services/network-status/useNetworkStatus.ts
@@ -0,0 +1,28 @@
+"use client";
+
+import { useEffect } from "react";
+import { toast } from "sonner";
+
+export function useNetworkStatus() {
+ useEffect(function monitorNetworkStatus() {
+ function handleOnline() {
+ toast.success("Connection restored", {
+ description: "You're back online",
+ });
+ }
+
+ function handleOffline() {
+ toast.error("You're offline", {
+ description: "Check your internet connection",
+ });
+ }
+
+ window.addEventListener("online", handleOnline);
+ window.addEventListener("offline", handleOffline);
+
+ return function cleanup() {
+ window.removeEventListener("online", handleOnline);
+ window.removeEventListener("offline", handleOffline);
+ };
+ }, []);
+}
diff --git a/autogpt_platform/frontend/src/services/storage/local-storage.ts b/autogpt_platform/frontend/src/services/storage/local-storage.ts
index 494ddc3ccc..a1aa63741a 100644
--- a/autogpt_platform/frontend/src/services/storage/local-storage.ts
+++ b/autogpt_platform/frontend/src/services/storage/local-storage.ts
@@ -10,6 +10,7 @@ export enum Key {
LIBRARY_AGENTS_CACHE = "library-agents-cache",
CHAT_SESSION_ID = "chat_session_id",
COOKIE_CONSENT = "autogpt_cookie_consent",
+ AI_AGENT_SAFETY_POPUP_SHOWN = "ai-agent-safety-popup-shown",
}
function get(key: Key) {
diff --git a/autogpt_platform/frontend/src/services/storage/session-storage.ts b/autogpt_platform/frontend/src/services/storage/session-storage.ts
index 8404da571c..1be82c98fb 100644
--- a/autogpt_platform/frontend/src/services/storage/session-storage.ts
+++ b/autogpt_platform/frontend/src/services/storage/session-storage.ts
@@ -3,6 +3,7 @@ import { environment } from "../environment";
export enum SessionKey {
CHAT_SENT_INITIAL_PROMPTS = "chat_sent_initial_prompts",
+ CHAT_INITIAL_PROMPTS = "chat_initial_prompts",
}
function get(key: SessionKey) {
diff --git a/autogpt_platform/frontend/src/tests/library.spec.ts b/autogpt_platform/frontend/src/tests/library.spec.ts
index 1972e94522..52941785e3 100644
--- a/autogpt_platform/frontend/src/tests/library.spec.ts
+++ b/autogpt_platform/frontend/src/tests/library.spec.ts
@@ -59,12 +59,13 @@ test.describe("Library", () => {
});
test("pagination works correctly", async ({ page }, testInfo) => {
- test.setTimeout(testInfo.timeout * 3); // Increase timeout for pagination operations
+ test.setTimeout(testInfo.timeout * 3);
await page.goto("/library");
+ const PAGE_SIZE = 20;
const paginationResult = await libraryPage.testPagination();
- if (paginationResult.initialCount >= 10) {
+ if (paginationResult.initialCount >= PAGE_SIZE) {
expect(paginationResult.finalCount).toBeGreaterThanOrEqual(
paginationResult.initialCount,
);
@@ -133,7 +134,10 @@ test.describe("Library", () => {
test.expect(clearedSearchValue).toBe("");
});
- test("pagination while searching works correctly", async ({ page }) => {
+ test("pagination while searching works correctly", async ({
+ page,
+ }, testInfo) => {
+ test.setTimeout(testInfo.timeout * 3);
await page.goto("/library");
const allAgents = await libraryPage.getAgents();
@@ -152,9 +156,10 @@ test.describe("Library", () => {
);
expect(matchingResults.length).toEqual(initialSearchResults.length);
+ const PAGE_SIZE = 20;
const searchPaginationResult = await libraryPage.testPagination();
- if (searchPaginationResult.initialCount >= 10) {
+ if (searchPaginationResult.initialCount >= PAGE_SIZE) {
expect(searchPaginationResult.finalCount).toBeGreaterThanOrEqual(
searchPaginationResult.initialCount,
);
diff --git a/autogpt_platform/frontend/src/tests/marketplace-creator.spec.ts b/autogpt_platform/frontend/src/tests/marketplace-creator.spec.ts
index 80ae09e508..89d0116127 100644
--- a/autogpt_platform/frontend/src/tests/marketplace-creator.spec.ts
+++ b/autogpt_platform/frontend/src/tests/marketplace-creator.spec.ts
@@ -13,9 +13,12 @@ test.describe("Marketplace Creator Page – Cross-Page Flows", () => {
await marketplacePage.getFirstCreatorProfile(page);
await firstCreatorProfile.click();
await page.waitForURL("**/marketplace/creator/**");
+ await page.waitForLoadState("networkidle").catch(() => {});
+
const firstAgent = page
.locator('[data-testid="store-card"]:visible')
.first();
+ await firstAgent.waitFor({ state: "visible", timeout: 30000 });
await firstAgent.click();
await page.waitForURL("**/marketplace/agent/**");
diff --git a/autogpt_platform/frontend/src/tests/marketplace.spec.ts b/autogpt_platform/frontend/src/tests/marketplace.spec.ts
index 83841c1030..934a44284f 100644
--- a/autogpt_platform/frontend/src/tests/marketplace.spec.ts
+++ b/autogpt_platform/frontend/src/tests/marketplace.spec.ts
@@ -11,7 +11,6 @@ test.describe("Marketplace – Navigation", () => {
const firstFeaturedAgent =
await marketplacePage.getFirstFeaturedAgent(page);
- await firstFeaturedAgent.waitFor({ state: "visible" });
await firstFeaturedAgent.click();
await page.waitForURL("**/marketplace/agent/**");
await matchesUrl(page, /\/marketplace\/agent\/.+/);
@@ -50,7 +49,15 @@ test.describe("Marketplace – Navigation", () => {
const searchTerm = page.getByText("DummyInput").first();
await isVisible(searchTerm);
- await page.waitForTimeout(10000);
+ await page.waitForLoadState("networkidle").catch(() => {});
+
+ await page
+ .waitForFunction(
+ () =>
+ document.querySelectorAll('[data-testid="store-card"]').length > 0,
+ { timeout: 15000 },
+ )
+ .catch(() => console.log("No search results appeared within timeout"));
const results = await marketplacePage.getSearchResultsCount(page);
expect(results).toBeGreaterThan(0);
diff --git a/autogpt_platform/frontend/src/tests/pages/library.page.ts b/autogpt_platform/frontend/src/tests/pages/library.page.ts
index 3a7695ec3a..03e98598b4 100644
--- a/autogpt_platform/frontend/src/tests/pages/library.page.ts
+++ b/autogpt_platform/frontend/src/tests/pages/library.page.ts
@@ -300,21 +300,27 @@ export class LibraryPage extends BasePage {
async scrollToLoadMore(): Promise {
console.log(`scrolling to load more agents`);
- // Get initial agent count
- const initialCount = await this.getAgentCount();
- console.log(`Initial agent count: ${initialCount}`);
+ const initialCount = await this.getAgentCountByListLength();
+ console.log(`Initial agent count (DOM cards): ${initialCount}`);
- // Scroll down to trigger pagination
await this.scrollToBottom();
- // Wait for potential new agents to load
- await this.page.waitForTimeout(2000);
+ await this.page
+ .waitForLoadState("networkidle", { timeout: 10000 })
+ .catch(() => console.log("Network idle timeout, continuing..."));
- // Check if more agents loaded
- const newCount = await this.getAgentCount();
- console.log(`New agent count after scroll: ${newCount}`);
+ await this.page
+ .waitForFunction(
+ (prevCount) =>
+ document.querySelectorAll('[data-testid="library-agent-card"]')
+ .length > prevCount,
+ initialCount,
+ { timeout: 5000 },
+ )
+ .catch(() => {});
- return;
+ const newCount = await this.getAgentCountByListLength();
+ console.log(`New agent count after scroll (DOM cards): ${newCount}`);
}
async testPagination(): Promise<{
diff --git a/autogpt_platform/frontend/src/tests/pages/login.page.ts b/autogpt_platform/frontend/src/tests/pages/login.page.ts
index 9082cc6219..adcb8d908b 100644
--- a/autogpt_platform/frontend/src/tests/pages/login.page.ts
+++ b/autogpt_platform/frontend/src/tests/pages/login.page.ts
@@ -37,9 +37,13 @@ export class LoginPage {
this.page.on("load", (page) => console.log(`ℹ️ Now at URL: ${page.url()}`));
// Start waiting for navigation before clicking
+ // Wait for redirect to marketplace, onboarding, library, or copilot (new landing pages)
const leaveLoginPage = this.page
.waitForURL(
- (url) => /^\/(marketplace|onboarding(\/.*)?)?$/.test(url.pathname),
+ (url: URL) =>
+ /^\/(marketplace|onboarding(\/.*)?|library|copilot)?$/.test(
+ url.pathname,
+ ),
{ timeout: 10_000 },
)
.catch((reason) => {
diff --git a/autogpt_platform/frontend/src/tests/pages/marketplace.page.ts b/autogpt_platform/frontend/src/tests/pages/marketplace.page.ts
index 20f60c371a..115a7b2f12 100644
--- a/autogpt_platform/frontend/src/tests/pages/marketplace.page.ts
+++ b/autogpt_platform/frontend/src/tests/pages/marketplace.page.ts
@@ -9,6 +9,7 @@ export class MarketplacePage extends BasePage {
async goto(page: Page) {
await page.goto("/marketplace");
+ await page.waitForLoadState("networkidle").catch(() => {});
}
async getMarketplaceTitle(page: Page) {
@@ -109,16 +110,24 @@ export class MarketplacePage extends BasePage {
async getFirstFeaturedAgent(page: Page) {
const { getId } = getSelectors(page);
- return getId("featured-store-card").first();
+ const card = getId("featured-store-card").first();
+ await card.waitFor({ state: "visible", timeout: 30000 });
+ return card;
}
async getFirstTopAgent() {
- return this.page.locator('[data-testid="store-card"]:visible').first();
+ const card = this.page
+ .locator('[data-testid="store-card"]:visible')
+ .first();
+ await card.waitFor({ state: "visible", timeout: 30000 });
+ return card;
}
async getFirstCreatorProfile(page: Page) {
const { getId } = getSelectors(page);
- return getId("creator-card").first();
+ const card = getId("creator-card").first();
+ await card.waitFor({ state: "visible", timeout: 30000 });
+ return card;
}
async getSearchResultsCount(page: Page) {
diff --git a/autogpt_platform/frontend/src/tests/utils/signup.ts b/autogpt_platform/frontend/src/tests/utils/signup.ts
index 7c8fdbe01b..192a9129b9 100644
--- a/autogpt_platform/frontend/src/tests/utils/signup.ts
+++ b/autogpt_platform/frontend/src/tests/utils/signup.ts
@@ -36,14 +36,16 @@ export async function signupTestUser(
const signupButton = getButton("Sign up");
await signupButton.click();
- // Wait for successful signup - could redirect to onboarding or marketplace
+ // Wait for successful signup - could redirect to various pages depending on onboarding state
try {
- // Wait for either onboarding or marketplace redirect
- await Promise.race([
- page.waitForURL(/\/onboarding/, { timeout: 15000 }),
- page.waitForURL(/\/marketplace/, { timeout: 15000 }),
- ]);
+ // Wait for redirect to onboarding, marketplace, copilot, or library
+ // Use a single waitForURL with a callback to avoid Promise.race race conditions
+ await page.waitForURL(
+ (url: URL) =>
+ /\/(onboarding|marketplace|copilot|library)/.test(url.pathname),
+ { timeout: 15000 },
+ );
} catch (error) {
console.error(
"❌ Timeout waiting for redirect, current URL:",
@@ -54,14 +56,19 @@ export async function signupTestUser(
const currentUrl = page.url();
- // Handle onboarding or marketplace redirect
+ // Handle onboarding redirect if needed
if (currentUrl.includes("/onboarding") && ignoreOnboarding) {
await page.goto("http://localhost:3000/marketplace");
await page.waitForLoadState("domcontentloaded", { timeout: 10000 });
}
- // Verify we're on the expected final page
- if (ignoreOnboarding || currentUrl.includes("/marketplace")) {
+ // Verify we're on an expected final page and user is authenticated
+ if (currentUrl.includes("/copilot") || currentUrl.includes("/library")) {
+ // For copilot/library landing pages, just verify user is authenticated
+ await page
+ .getByTestId("profile-popout-menu-trigger")
+ .waitFor({ state: "visible", timeout: 10000 });
+ } else if (ignoreOnboarding || currentUrl.includes("/marketplace")) {
// Verify we're on marketplace
await page
.getByText(
diff --git a/autogpt_platform/frontend/tailwind.config.ts b/autogpt_platform/frontend/tailwind.config.ts
index f560a5e3b9..1adc53bdc4 100644
--- a/autogpt_platform/frontend/tailwind.config.ts
+++ b/autogpt_platform/frontend/tailwind.config.ts
@@ -157,12 +157,21 @@ const config = {
backgroundPosition: "-200% 0",
},
},
+ loader: {
+ "0%": {
+ boxShadow: "0 0 0 0 rgba(0, 0, 0, 0.25)",
+ },
+ "100%": {
+ boxShadow: "0 0 0 30px rgba(0, 0, 0, 0)",
+ },
+ },
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
"fade-in": "fade-in 0.2s ease-out",
shimmer: "shimmer 2s ease-in-out infinite",
+ loader: "loader 1s infinite",
},
transitionDuration: {
"2000": "2000ms",
diff --git a/backend/blocks/video/__init__.py b/backend/blocks/video/__init__.py
deleted file mode 100644
index fd95ef9a58..0000000000
--- a/backend/blocks/video/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# Video editing blocks
diff --git a/docs/integrations/.gitbook/assets/Ollama-Add-Prompts.png b/docs/integrations/.gitbook/assets/Ollama-Add-Prompts.png
new file mode 100644
index 0000000000..deeddc7cc8
Binary files /dev/null and b/docs/integrations/.gitbook/assets/Ollama-Add-Prompts.png differ
diff --git a/docs/integrations/.gitbook/assets/Ollama-Output.png b/docs/integrations/.gitbook/assets/Ollama-Output.png
new file mode 100644
index 0000000000..06cb9f7a8a
Binary files /dev/null and b/docs/integrations/.gitbook/assets/Ollama-Output.png differ
diff --git a/docs/integrations/.gitbook/assets/Ollama-Remote-Host.png b/docs/integrations/.gitbook/assets/Ollama-Remote-Host.png
new file mode 100644
index 0000000000..25a57b9adf
Binary files /dev/null and b/docs/integrations/.gitbook/assets/Ollama-Remote-Host.png differ
diff --git a/docs/integrations/.gitbook/assets/Ollama-Select-Llama32.png b/docs/integrations/.gitbook/assets/Ollama-Select-Llama32.png
new file mode 100644
index 0000000000..cd39e1b4e6
Binary files /dev/null and b/docs/integrations/.gitbook/assets/Ollama-Select-Llama32.png differ
diff --git a/docs/integrations/.gitbook/assets/Select-AI-block.png b/docs/integrations/.gitbook/assets/Select-AI-block.png
new file mode 100644
index 0000000000..d9c41db4a5
Binary files /dev/null and b/docs/integrations/.gitbook/assets/Select-AI-block.png differ
diff --git a/docs/integrations/.gitbook/assets/e2b-dashboard.png b/docs/integrations/.gitbook/assets/e2b-dashboard.png
new file mode 100644
index 0000000000..456f1490cc
Binary files /dev/null and b/docs/integrations/.gitbook/assets/e2b-dashboard.png differ
diff --git a/docs/integrations/.gitbook/assets/e2b-log-url.png b/docs/integrations/.gitbook/assets/e2b-log-url.png
new file mode 100644
index 0000000000..3f1c189ee5
Binary files /dev/null and b/docs/integrations/.gitbook/assets/e2b-log-url.png differ
diff --git a/docs/integrations/.gitbook/assets/e2b-new-tag.png b/docs/integrations/.gitbook/assets/e2b-new-tag.png
new file mode 100644
index 0000000000..65a0a767cd
Binary files /dev/null and b/docs/integrations/.gitbook/assets/e2b-new-tag.png differ
diff --git a/docs/integrations/.gitbook/assets/e2b-tag-button.png b/docs/integrations/.gitbook/assets/e2b-tag-button.png
new file mode 100644
index 0000000000..741a6bac1a
Binary files /dev/null and b/docs/integrations/.gitbook/assets/e2b-tag-button.png differ
diff --git a/docs/integrations/.gitbook/assets/get-repo-dialog.png b/docs/integrations/.gitbook/assets/get-repo-dialog.png
new file mode 100644
index 0000000000..813160e45c
Binary files /dev/null and b/docs/integrations/.gitbook/assets/get-repo-dialog.png differ
diff --git a/docs/integrations/README.md b/docs/integrations/README.md
index e444757a49..263d7e6365 100644
--- a/docs/integrations/README.md
+++ b/docs/integrations/README.md
@@ -1,12 +1,32 @@
+---
+layout:
+ width: default
+ title:
+ visible: true
+ description:
+ visible: true
+ tableOfContents:
+ visible: false
+ outline:
+ visible: true
+ pagination:
+ visible: true
+ metadata:
+ visible: true
+---
+
# AutoGPT Blocks Overview
AutoGPT uses a modular approach with various "blocks" to handle different tasks. These blocks are the building blocks of AutoGPT workflows, allowing users to create complex automations by combining simple, specialized components.
-!!! info "Creating Your Own Blocks"
- Want to create your own custom blocks? Check out our guides:
-
- - [Build your own Blocks](https://docs.agpt.co/platform/new_blocks/) - Step-by-step tutorial with examples
- - [Block SDK Guide](https://docs.agpt.co/platform/block-sdk-guide/) - Advanced SDK patterns with OAuth, webhooks, and provider configuration
+{% hint style="info" %}
+**Creating Your Own Blocks**
+
+Want to create your own custom blocks? Check out our guides:
+
+* [Build your own Blocks](https://docs.agpt.co/platform/new_blocks/) - Step-by-step tutorial with examples
+* [Block SDK Guide](https://docs.agpt.co/platform/block-sdk-guide/) - Advanced SDK patterns with OAuth, webhooks, and provider configuration
+{% endhint %}
Below is a comprehensive list of all available blocks, categorized by their primary function. Click on any block name to view its detailed documentation.
@@ -14,546 +34,547 @@ Below is a comprehensive list of all available blocks, categorized by their prim
| Block Name | Description |
|------------|-------------|
-| [Add Memory](basic.md#add-memory) | Add new memories to Mem0 with user segmentation |
-| [Add To Dictionary](basic.md#add-to-dictionary) | Adds a new key-value pair to a dictionary |
-| [Add To Library From Store](system/library_operations.md#add-to-library-from-store) | Add an agent from the store to your personal library |
-| [Add To List](basic.md#add-to-list) | Adds a new entry to a list |
-| [Agent Date Input](basic.md#agent-date-input) | Block for date input |
-| [Agent Dropdown Input](basic.md#agent-dropdown-input) | Block for dropdown text selection |
-| [Agent File Input](basic.md#agent-file-input) | Block for file upload input (string path for example) |
-| [Agent Google Drive File Input](basic.md#agent-google-drive-file-input) | Block for selecting a file from Google Drive |
-| [Agent Input](basic.md#agent-input) | A block that accepts and processes user input values within a workflow, supporting various input types and validation |
-| [Agent Long Text Input](basic.md#agent-long-text-input) | Block for long text input (multi-line) |
-| [Agent Number Input](basic.md#agent-number-input) | Block for number input |
-| [Agent Output](basic.md#agent-output) | A block that records and formats workflow results for display to users, with optional Jinja2 template formatting support |
-| [Agent Short Text Input](basic.md#agent-short-text-input) | Block for short text input (single-line) |
-| [Agent Table Input](basic.md#agent-table-input) | Block for table data input with customizable headers |
-| [Agent Time Input](basic.md#agent-time-input) | Block for time input |
-| [Agent Toggle Input](basic.md#agent-toggle-input) | Block for boolean toggle input |
-| [Block Installation](basic.md#block-installation) | Given a code string, this block allows the verification and installation of a block code into the system |
-| [Concatenate Lists](basic.md#concatenate-lists) | Concatenates multiple lists into a single list |
-| [Dictionary Is Empty](basic.md#dictionary-is-empty) | Checks if a dictionary is empty |
-| [File Store](basic.md#file-store) | Stores the input file in the temporary directory |
-| [Find In Dictionary](basic.md#find-in-dictionary) | A block that looks up a value in a dictionary, list, or object by key or index and returns the corresponding value |
-| [Find In List](basic.md#find-in-list) | Finds the index of the value in the list |
-| [Get All Memories](basic.md#get-all-memories) | Retrieve all memories from Mem0 with optional conversation filtering |
-| [Get Latest Memory](basic.md#get-latest-memory) | Retrieve the latest memory from Mem0 with optional key filtering |
-| [Get List Item](basic.md#get-list-item) | Returns the element at the given index |
-| [Get Store Agent Details](system/store_operations.md#get-store-agent-details) | Get detailed information about an agent from the store |
-| [Get Weather Information](basic.md#get-weather-information) | Retrieves weather information for a specified location using OpenWeatherMap API |
-| [Human In The Loop](basic.md#human-in-the-loop) | Pause execution and wait for human approval or modification of data |
-| [Linear Search Issues](linear/issues.md#linear-search-issues) | Searches for issues on Linear |
-| [List Is Empty](basic.md#list-is-empty) | Checks if a list is empty |
-| [List Library Agents](system/library_operations.md#list-library-agents) | List all agents in your personal library |
-| [Note](basic.md#note) | A visual annotation block that displays a sticky note in the workflow editor for documentation and organization purposes |
-| [Print To Console](basic.md#print-to-console) | A debugging block that outputs text to the console for monitoring and troubleshooting workflow execution |
-| [Remove From Dictionary](basic.md#remove-from-dictionary) | Removes a key-value pair from a dictionary |
-| [Remove From List](basic.md#remove-from-list) | Removes an item from a list by value or index |
-| [Replace Dictionary Value](basic.md#replace-dictionary-value) | Replaces the value for a specified key in a dictionary |
-| [Replace List Item](basic.md#replace-list-item) | Replaces an item at the specified index |
-| [Reverse List Order](basic.md#reverse-list-order) | Reverses the order of elements in a list |
-| [Search Memory](basic.md#search-memory) | Search memories in Mem0 by user |
-| [Search Store Agents](system/store_operations.md#search-store-agents) | Search for agents in the store |
-| [Slant3D Cancel Order](slant3d/order.md#slant3d-cancel-order) | Cancel an existing order |
-| [Slant3D Create Order](slant3d/order.md#slant3d-create-order) | Create a new print order |
-| [Slant3D Estimate Order](slant3d/order.md#slant3d-estimate-order) | Get order cost estimate |
-| [Slant3D Estimate Shipping](slant3d/order.md#slant3d-estimate-shipping) | Get shipping cost estimate |
-| [Slant3D Filament](slant3d/filament.md#slant3d-filament) | Get list of available filaments |
-| [Slant3D Get Orders](slant3d/order.md#slant3d-get-orders) | Get all orders for the account |
-| [Slant3D Slicer](slant3d/slicing.md#slant3d-slicer) | Slice a 3D model file and get pricing information |
-| [Slant3D Tracking](slant3d/order.md#slant3d-tracking) | Track order status and shipping |
-| [Store Value](basic.md#store-value) | A basic block that stores and forwards a value throughout workflows, allowing it to be reused without changes across multiple blocks |
-| [Universal Type Converter](basic.md#universal-type-converter) | This block is used to convert a value to a universal type |
-| [XML Parser](basic.md#xml-parser) | Parses XML using gravitasml to tokenize and coverts it to dict |
+| [Add Memory](block-integrations/basic.md#add-memory) | Add new memories to Mem0 with user segmentation |
+| [Add To Dictionary](block-integrations/basic.md#add-to-dictionary) | Adds a new key-value pair to a dictionary |
+| [Add To Library From Store](block-integrations/system/library_operations.md#add-to-library-from-store) | Add an agent from the store to your personal library |
+| [Add To List](block-integrations/basic.md#add-to-list) | Adds a new entry to a list |
+| [Agent Date Input](block-integrations/basic.md#agent-date-input) | Block for date input |
+| [Agent Dropdown Input](block-integrations/basic.md#agent-dropdown-input) | Block for dropdown text selection |
+| [Agent File Input](block-integrations/basic.md#agent-file-input) | Block for file upload input (string path for example) |
+| [Agent Google Drive File Input](block-integrations/basic.md#agent-google-drive-file-input) | Block for selecting a file from Google Drive |
+| [Agent Input](block-integrations/basic.md#agent-input) | A block that accepts and processes user input values within a workflow, supporting various input types and validation |
+| [Agent Long Text Input](block-integrations/basic.md#agent-long-text-input) | Block for long text input (multi-line) |
+| [Agent Number Input](block-integrations/basic.md#agent-number-input) | Block for number input |
+| [Agent Output](block-integrations/basic.md#agent-output) | A block that records and formats workflow results for display to users, with optional Jinja2 template formatting support |
+| [Agent Short Text Input](block-integrations/basic.md#agent-short-text-input) | Block for short text input (single-line) |
+| [Agent Table Input](block-integrations/basic.md#agent-table-input) | Block for table data input with customizable headers |
+| [Agent Time Input](block-integrations/basic.md#agent-time-input) | Block for time input |
+| [Agent Toggle Input](block-integrations/basic.md#agent-toggle-input) | Block for boolean toggle input |
+| [Block Installation](block-integrations/basic.md#block-installation) | Given a code string, this block allows the verification and installation of a block code into the system |
+| [Concatenate Lists](block-integrations/basic.md#concatenate-lists) | Concatenates multiple lists into a single list |
+| [Dictionary Is Empty](block-integrations/basic.md#dictionary-is-empty) | Checks if a dictionary is empty |
+| [File Store](block-integrations/basic.md#file-store) | Downloads and stores a file from a URL, data URI, or local path |
+| [Find In Dictionary](block-integrations/basic.md#find-in-dictionary) | A block that looks up a value in a dictionary, list, or object by key or index and returns the corresponding value |
+| [Find In List](block-integrations/basic.md#find-in-list) | Finds the index of the value in the list |
+| [Get All Memories](block-integrations/basic.md#get-all-memories) | Retrieve all memories from Mem0 with optional conversation filtering |
+| [Get Latest Memory](block-integrations/basic.md#get-latest-memory) | Retrieve the latest memory from Mem0 with optional key filtering |
+| [Get List Item](block-integrations/basic.md#get-list-item) | Returns the element at the given index |
+| [Get Store Agent Details](block-integrations/system/store_operations.md#get-store-agent-details) | Get detailed information about an agent from the store |
+| [Get Weather Information](block-integrations/basic.md#get-weather-information) | Retrieves weather information for a specified location using OpenWeatherMap API |
+| [Human In The Loop](block-integrations/basic.md#human-in-the-loop) | Pause execution and wait for human approval or modification of data |
+| [Linear Search Issues](block-integrations/linear/issues.md#linear-search-issues) | Searches for issues on Linear |
+| [List Is Empty](block-integrations/basic.md#list-is-empty) | Checks if a list is empty |
+| [List Library Agents](block-integrations/system/library_operations.md#list-library-agents) | List all agents in your personal library |
+| [Note](block-integrations/basic.md#note) | A visual annotation block that displays a sticky note in the workflow editor for documentation and organization purposes |
+| [Print To Console](block-integrations/basic.md#print-to-console) | A debugging block that outputs text to the console for monitoring and troubleshooting workflow execution |
+| [Remove From Dictionary](block-integrations/basic.md#remove-from-dictionary) | Removes a key-value pair from a dictionary |
+| [Remove From List](block-integrations/basic.md#remove-from-list) | Removes an item from a list by value or index |
+| [Replace Dictionary Value](block-integrations/basic.md#replace-dictionary-value) | Replaces the value for a specified key in a dictionary |
+| [Replace List Item](block-integrations/basic.md#replace-list-item) | Replaces an item at the specified index |
+| [Reverse List Order](block-integrations/basic.md#reverse-list-order) | Reverses the order of elements in a list |
+| [Search Memory](block-integrations/basic.md#search-memory) | Search memories in Mem0 by user |
+| [Search Store Agents](block-integrations/system/store_operations.md#search-store-agents) | Search for agents in the store |
+| [Slant3D Cancel Order](block-integrations/slant3d/order.md#slant3d-cancel-order) | Cancel an existing order |
+| [Slant3D Create Order](block-integrations/slant3d/order.md#slant3d-create-order) | Create a new print order |
+| [Slant3D Estimate Order](block-integrations/slant3d/order.md#slant3d-estimate-order) | Get order cost estimate |
+| [Slant3D Estimate Shipping](block-integrations/slant3d/order.md#slant3d-estimate-shipping) | Get shipping cost estimate |
+| [Slant3D Filament](block-integrations/slant3d/filament.md#slant3d-filament) | Get list of available filaments |
+| [Slant3D Get Orders](block-integrations/slant3d/order.md#slant3d-get-orders) | Get all orders for the account |
+| [Slant3D Slicer](block-integrations/slant3d/slicing.md#slant3d-slicer) | Slice a 3D model file and get pricing information |
+| [Slant3D Tracking](block-integrations/slant3d/order.md#slant3d-tracking) | Track order status and shipping |
+| [Store Value](block-integrations/basic.md#store-value) | A basic block that stores and forwards a value throughout workflows, allowing it to be reused without changes across multiple blocks |
+| [Universal Type Converter](block-integrations/basic.md#universal-type-converter) | This block is used to convert a value to a universal type |
+| [XML Parser](block-integrations/basic.md#xml-parser) | Parses XML using gravitasml to tokenize and coverts it to dict |
## Data Processing
| Block Name | Description |
|------------|-------------|
-| [Airtable Create Base](airtable/bases.md#airtable-create-base) | Create or find a base in Airtable |
-| [Airtable Create Field](airtable/schema.md#airtable-create-field) | Add a new field to an Airtable table |
-| [Airtable Create Records](airtable/records.md#airtable-create-records) | Create records in an Airtable table |
-| [Airtable Create Table](airtable/schema.md#airtable-create-table) | Create a new table in an Airtable base |
-| [Airtable Delete Records](airtable/records.md#airtable-delete-records) | Delete records from an Airtable table |
-| [Airtable Get Record](airtable/records.md#airtable-get-record) | Get a single record from Airtable |
-| [Airtable List Bases](airtable/bases.md#airtable-list-bases) | List all bases in Airtable |
-| [Airtable List Records](airtable/records.md#airtable-list-records) | List records from an Airtable table |
-| [Airtable List Schema](airtable/schema.md#airtable-list-schema) | Get the complete schema of an Airtable base |
-| [Airtable Update Field](airtable/schema.md#airtable-update-field) | Update field properties in an Airtable table |
-| [Airtable Update Records](airtable/records.md#airtable-update-records) | Update records in an Airtable table |
-| [Airtable Update Table](airtable/schema.md#airtable-update-table) | Update table properties |
-| [Airtable Webhook Trigger](airtable/triggers.md#airtable-webhook-trigger) | Starts a flow whenever Airtable emits a webhook event |
-| [Baas Bot Delete Recording](baas/bots.md#baas-bot-delete-recording) | Permanently delete a meeting's recorded data |
-| [Baas Bot Fetch Meeting Data](baas/bots.md#baas-bot-fetch-meeting-data) | Retrieve recorded meeting data |
-| [Create Dictionary](data.md#create-dictionary) | Creates a dictionary with the specified key-value pairs |
-| [Create List](data.md#create-list) | Creates a list with the specified values |
-| [Data For Seo Keyword Suggestions](dataforseo/keyword_suggestions.md#data-for-seo-keyword-suggestions) | Get keyword suggestions from DataForSEO Labs Google API |
-| [Data For Seo Related Keywords](dataforseo/related_keywords.md#data-for-seo-related-keywords) | Get related keywords from DataForSEO Labs Google API |
-| [Exa Create Import](exa/websets_import_export.md#exa-create-import) | Import CSV data to use with websets for targeted searches |
-| [Exa Delete Import](exa/websets_import_export.md#exa-delete-import) | Delete an import |
-| [Exa Export Webset](exa/websets_import_export.md#exa-export-webset) | Export webset data in JSON, CSV, or JSON Lines format |
-| [Exa Get Import](exa/websets_import_export.md#exa-get-import) | Get the status and details of an import |
-| [Exa Get New Items](exa/websets_items.md#exa-get-new-items) | Get items added since a cursor - enables incremental processing without reprocessing |
-| [Exa List Imports](exa/websets_import_export.md#exa-list-imports) | List all imports with pagination support |
-| [File Read](data.md#file-read) | Reads a file and returns its content as a string, with optional chunking by delimiter and size limits |
-| [Google Calendar Read Events](google/calendar.md#google-calendar-read-events) | Retrieves upcoming events from a Google Calendar with filtering options |
-| [Google Docs Append Markdown](google/docs.md#google-docs-append-markdown) | Append Markdown content to the end of a Google Doc with full formatting - ideal for LLM/AI output |
-| [Google Docs Append Plain Text](google/docs.md#google-docs-append-plain-text) | Append plain text to the end of a Google Doc (no formatting applied) |
-| [Google Docs Create](google/docs.md#google-docs-create) | Create a new Google Doc |
-| [Google Docs Delete Content](google/docs.md#google-docs-delete-content) | Delete a range of content from a Google Doc |
-| [Google Docs Export](google/docs.md#google-docs-export) | Export a Google Doc to PDF, Word, text, or other formats |
-| [Google Docs Find Replace Plain Text](google/docs.md#google-docs-find-replace-plain-text) | Find and replace plain text in a Google Doc (no formatting applied to replacement) |
-| [Google Docs Format Text](google/docs.md#google-docs-format-text) | Apply formatting (bold, italic, color, etc |
-| [Google Docs Get Metadata](google/docs.md#google-docs-get-metadata) | Get metadata about a Google Doc |
-| [Google Docs Get Structure](google/docs.md#google-docs-get-structure) | Get document structure with index positions for precise editing operations |
-| [Google Docs Insert Markdown At](google/docs.md#google-docs-insert-markdown-at) | Insert formatted Markdown at a specific position in a Google Doc - ideal for LLM/AI output |
-| [Google Docs Insert Page Break](google/docs.md#google-docs-insert-page-break) | Insert a page break into a Google Doc |
-| [Google Docs Insert Plain Text](google/docs.md#google-docs-insert-plain-text) | Insert plain text at a specific position in a Google Doc (no formatting applied) |
-| [Google Docs Insert Table](google/docs.md#google-docs-insert-table) | Insert a table into a Google Doc, optionally with content and Markdown formatting |
-| [Google Docs Read](google/docs.md#google-docs-read) | Read text content from a Google Doc |
-| [Google Docs Replace All With Markdown](google/docs.md#google-docs-replace-all-with-markdown) | Replace entire Google Doc content with formatted Markdown - ideal for LLM/AI output |
-| [Google Docs Replace Content With Markdown](google/docs.md#google-docs-replace-content-with-markdown) | Find text and replace it with formatted Markdown - ideal for LLM/AI output and templates |
-| [Google Docs Replace Range With Markdown](google/docs.md#google-docs-replace-range-with-markdown) | Replace a specific index range in a Google Doc with formatted Markdown - ideal for LLM/AI output |
-| [Google Docs Set Public Access](google/docs.md#google-docs-set-public-access) | Make a Google Doc public or private |
-| [Google Docs Share](google/docs.md#google-docs-share) | Share a Google Doc with specific users |
-| [Google Sheets Add Column](google/sheets.md#google-sheets-add-column) | Add a new column with a header |
-| [Google Sheets Add Dropdown](google/sheets.md#google-sheets-add-dropdown) | Add a dropdown list (data validation) to cells |
-| [Google Sheets Add Note](google/sheets.md#google-sheets-add-note) | Add a note to a cell in a Google Sheet |
-| [Google Sheets Append Row](google/sheets.md#google-sheets-append-row) | Append or Add a single row to the end of a Google Sheet |
-| [Google Sheets Batch Operations](google/sheets.md#google-sheets-batch-operations) | This block performs multiple operations on a Google Sheets spreadsheet in a single batch request |
-| [Google Sheets Clear](google/sheets.md#google-sheets-clear) | This block clears data from a specified range in a Google Sheets spreadsheet |
-| [Google Sheets Copy To Spreadsheet](google/sheets.md#google-sheets-copy-to-spreadsheet) | Copy a sheet from one spreadsheet to another |
-| [Google Sheets Create Named Range](google/sheets.md#google-sheets-create-named-range) | Create a named range to reference cells by name instead of A1 notation |
-| [Google Sheets Create Spreadsheet](google/sheets.md#google-sheets-create-spreadsheet) | This block creates a new Google Sheets spreadsheet with specified sheets |
-| [Google Sheets Delete Column](google/sheets.md#google-sheets-delete-column) | Delete a column by header name or column letter |
-| [Google Sheets Delete Rows](google/sheets.md#google-sheets-delete-rows) | Delete specific rows from a Google Sheet by their row indices |
-| [Google Sheets Export Csv](google/sheets.md#google-sheets-export-csv) | Export a Google Sheet as CSV data |
-| [Google Sheets Filter Rows](google/sheets.md#google-sheets-filter-rows) | Filter rows in a Google Sheet based on a column condition |
-| [Google Sheets Find](google/sheets.md#google-sheets-find) | Find text in a Google Sheets spreadsheet |
-| [Google Sheets Find Replace](google/sheets.md#google-sheets-find-replace) | This block finds and replaces text in a Google Sheets spreadsheet |
-| [Google Sheets Format](google/sheets.md#google-sheets-format) | Format a range in a Google Sheet (sheet optional) |
-| [Google Sheets Get Column](google/sheets.md#google-sheets-get-column) | Extract all values from a specific column |
-| [Google Sheets Get Notes](google/sheets.md#google-sheets-get-notes) | Get notes from cells in a Google Sheet |
-| [Google Sheets Get Row](google/sheets.md#google-sheets-get-row) | Get a specific row by its index |
-| [Google Sheets Get Row Count](google/sheets.md#google-sheets-get-row-count) | Get row count and dimensions of a Google Sheet |
-| [Google Sheets Get Unique Values](google/sheets.md#google-sheets-get-unique-values) | Get unique values from a column |
-| [Google Sheets Import Csv](google/sheets.md#google-sheets-import-csv) | Import CSV data into a Google Sheet |
-| [Google Sheets Insert Row](google/sheets.md#google-sheets-insert-row) | Insert a single row at a specific position |
-| [Google Sheets List Named Ranges](google/sheets.md#google-sheets-list-named-ranges) | List all named ranges in a spreadsheet |
-| [Google Sheets Lookup Row](google/sheets.md#google-sheets-lookup-row) | Look up a row by finding a value in a specific column |
-| [Google Sheets Manage Sheet](google/sheets.md#google-sheets-manage-sheet) | Create, delete, or copy sheets (sheet optional) |
-| [Google Sheets Metadata](google/sheets.md#google-sheets-metadata) | This block retrieves metadata about a Google Sheets spreadsheet including sheet names and properties |
-| [Google Sheets Protect Range](google/sheets.md#google-sheets-protect-range) | Protect a cell range or entire sheet from editing |
-| [Google Sheets Read](google/sheets.md#google-sheets-read) | A block that reads data from a Google Sheets spreadsheet using A1 notation range selection |
-| [Google Sheets Remove Duplicates](google/sheets.md#google-sheets-remove-duplicates) | Remove duplicate rows based on specified columns |
-| [Google Sheets Set Public Access](google/sheets.md#google-sheets-set-public-access) | Make a Google Spreadsheet public or private |
-| [Google Sheets Share Spreadsheet](google/sheets.md#google-sheets-share-spreadsheet) | Share a Google Spreadsheet with users or get shareable link |
-| [Google Sheets Sort](google/sheets.md#google-sheets-sort) | Sort a Google Sheet by one or two columns |
-| [Google Sheets Update Cell](google/sheets.md#google-sheets-update-cell) | Update a single cell in a Google Sheets spreadsheet |
-| [Google Sheets Update Row](google/sheets.md#google-sheets-update-row) | Update a specific row by its index |
-| [Google Sheets Write](google/sheets.md#google-sheets-write) | A block that writes data to a Google Sheets spreadsheet at a specified A1 notation range |
-| [Keyword Suggestion Extractor](dataforseo/keyword_suggestions.md#keyword-suggestion-extractor) | Extract individual fields from a KeywordSuggestion object |
-| [Persist Information](data.md#persist-information) | Persist key-value information for the current user |
-| [Read Spreadsheet](data.md#read-spreadsheet) | Reads CSV and Excel files and outputs the data as a list of dictionaries and individual rows |
-| [Related Keyword Extractor](dataforseo/related_keywords.md#related-keyword-extractor) | Extract individual fields from a RelatedKeyword object |
-| [Retrieve Information](data.md#retrieve-information) | Retrieve key-value information for the current user |
-| [Screenshot Web Page](data.md#screenshot-web-page) | Takes a screenshot of a specified website using ScreenshotOne API |
+| [Airtable Create Base](block-integrations/airtable/bases.md#airtable-create-base) | Create or find a base in Airtable |
+| [Airtable Create Field](block-integrations/airtable/schema.md#airtable-create-field) | Add a new field to an Airtable table |
+| [Airtable Create Records](block-integrations/airtable/records.md#airtable-create-records) | Create records in an Airtable table |
+| [Airtable Create Table](block-integrations/airtable/schema.md#airtable-create-table) | Create a new table in an Airtable base |
+| [Airtable Delete Records](block-integrations/airtable/records.md#airtable-delete-records) | Delete records from an Airtable table |
+| [Airtable Get Record](block-integrations/airtable/records.md#airtable-get-record) | Get a single record from Airtable |
+| [Airtable List Bases](block-integrations/airtable/bases.md#airtable-list-bases) | List all bases in Airtable |
+| [Airtable List Records](block-integrations/airtable/records.md#airtable-list-records) | List records from an Airtable table |
+| [Airtable List Schema](block-integrations/airtable/schema.md#airtable-list-schema) | Get the complete schema of an Airtable base |
+| [Airtable Update Field](block-integrations/airtable/schema.md#airtable-update-field) | Update field properties in an Airtable table |
+| [Airtable Update Records](block-integrations/airtable/records.md#airtable-update-records) | Update records in an Airtable table |
+| [Airtable Update Table](block-integrations/airtable/schema.md#airtable-update-table) | Update table properties |
+| [Airtable Webhook Trigger](block-integrations/airtable/triggers.md#airtable-webhook-trigger) | Starts a flow whenever Airtable emits a webhook event |
+| [Baas Bot Delete Recording](block-integrations/baas/bots.md#baas-bot-delete-recording) | Permanently delete a meeting's recorded data |
+| [Baas Bot Fetch Meeting Data](block-integrations/baas/bots.md#baas-bot-fetch-meeting-data) | Retrieve recorded meeting data |
+| [Create Dictionary](block-integrations/data.md#create-dictionary) | Creates a dictionary with the specified key-value pairs |
+| [Create List](block-integrations/data.md#create-list) | Creates a list with the specified values |
+| [Data For Seo Keyword Suggestions](block-integrations/dataforseo/keyword_suggestions.md#data-for-seo-keyword-suggestions) | Get keyword suggestions from DataForSEO Labs Google API |
+| [Data For Seo Related Keywords](block-integrations/dataforseo/related_keywords.md#data-for-seo-related-keywords) | Get related keywords from DataForSEO Labs Google API |
+| [Exa Create Import](block-integrations/exa/websets_import_export.md#exa-create-import) | Import CSV data to use with websets for targeted searches |
+| [Exa Delete Import](block-integrations/exa/websets_import_export.md#exa-delete-import) | Delete an import |
+| [Exa Export Webset](block-integrations/exa/websets_import_export.md#exa-export-webset) | Export webset data in JSON, CSV, or JSON Lines format |
+| [Exa Get Import](block-integrations/exa/websets_import_export.md#exa-get-import) | Get the status and details of an import |
+| [Exa Get New Items](block-integrations/exa/websets_items.md#exa-get-new-items) | Get items added since a cursor - enables incremental processing without reprocessing |
+| [Exa List Imports](block-integrations/exa/websets_import_export.md#exa-list-imports) | List all imports with pagination support |
+| [File Read](block-integrations/data.md#file-read) | Reads a file and returns its content as a string, with optional chunking by delimiter and size limits |
+| [Google Calendar Read Events](block-integrations/google/calendar.md#google-calendar-read-events) | Retrieves upcoming events from a Google Calendar with filtering options |
+| [Google Docs Append Markdown](block-integrations/google/docs.md#google-docs-append-markdown) | Append Markdown content to the end of a Google Doc with full formatting - ideal for LLM/AI output |
+| [Google Docs Append Plain Text](block-integrations/google/docs.md#google-docs-append-plain-text) | Append plain text to the end of a Google Doc (no formatting applied) |
+| [Google Docs Create](block-integrations/google/docs.md#google-docs-create) | Create a new Google Doc |
+| [Google Docs Delete Content](block-integrations/google/docs.md#google-docs-delete-content) | Delete a range of content from a Google Doc |
+| [Google Docs Export](block-integrations/google/docs.md#google-docs-export) | Export a Google Doc to PDF, Word, text, or other formats |
+| [Google Docs Find Replace Plain Text](block-integrations/google/docs.md#google-docs-find-replace-plain-text) | Find and replace plain text in a Google Doc (no formatting applied to replacement) |
+| [Google Docs Format Text](block-integrations/google/docs.md#google-docs-format-text) | Apply formatting (bold, italic, color, etc |
+| [Google Docs Get Metadata](block-integrations/google/docs.md#google-docs-get-metadata) | Get metadata about a Google Doc |
+| [Google Docs Get Structure](block-integrations/google/docs.md#google-docs-get-structure) | Get document structure with index positions for precise editing operations |
+| [Google Docs Insert Markdown At](block-integrations/google/docs.md#google-docs-insert-markdown-at) | Insert formatted Markdown at a specific position in a Google Doc - ideal for LLM/AI output |
+| [Google Docs Insert Page Break](block-integrations/google/docs.md#google-docs-insert-page-break) | Insert a page break into a Google Doc |
+| [Google Docs Insert Plain Text](block-integrations/google/docs.md#google-docs-insert-plain-text) | Insert plain text at a specific position in a Google Doc (no formatting applied) |
+| [Google Docs Insert Table](block-integrations/google/docs.md#google-docs-insert-table) | Insert a table into a Google Doc, optionally with content and Markdown formatting |
+| [Google Docs Read](block-integrations/google/docs.md#google-docs-read) | Read text content from a Google Doc |
+| [Google Docs Replace All With Markdown](block-integrations/google/docs.md#google-docs-replace-all-with-markdown) | Replace entire Google Doc content with formatted Markdown - ideal for LLM/AI output |
+| [Google Docs Replace Content With Markdown](block-integrations/google/docs.md#google-docs-replace-content-with-markdown) | Find text and replace it with formatted Markdown - ideal for LLM/AI output and templates |
+| [Google Docs Replace Range With Markdown](block-integrations/google/docs.md#google-docs-replace-range-with-markdown) | Replace a specific index range in a Google Doc with formatted Markdown - ideal for LLM/AI output |
+| [Google Docs Set Public Access](block-integrations/google/docs.md#google-docs-set-public-access) | Make a Google Doc public or private |
+| [Google Docs Share](block-integrations/google/docs.md#google-docs-share) | Share a Google Doc with specific users |
+| [Google Sheets Add Column](block-integrations/google/sheets.md#google-sheets-add-column) | Add a new column with a header |
+| [Google Sheets Add Dropdown](block-integrations/google/sheets.md#google-sheets-add-dropdown) | Add a dropdown list (data validation) to cells |
+| [Google Sheets Add Note](block-integrations/google/sheets.md#google-sheets-add-note) | Add a note to a cell in a Google Sheet |
+| [Google Sheets Append Row](block-integrations/google/sheets.md#google-sheets-append-row) | Append or Add a single row to the end of a Google Sheet |
+| [Google Sheets Batch Operations](block-integrations/google/sheets.md#google-sheets-batch-operations) | This block performs multiple operations on a Google Sheets spreadsheet in a single batch request |
+| [Google Sheets Clear](block-integrations/google/sheets.md#google-sheets-clear) | This block clears data from a specified range in a Google Sheets spreadsheet |
+| [Google Sheets Copy To Spreadsheet](block-integrations/google/sheets.md#google-sheets-copy-to-spreadsheet) | Copy a sheet from one spreadsheet to another |
+| [Google Sheets Create Named Range](block-integrations/google/sheets.md#google-sheets-create-named-range) | Create a named range to reference cells by name instead of A1 notation |
+| [Google Sheets Create Spreadsheet](block-integrations/google/sheets.md#google-sheets-create-spreadsheet) | This block creates a new Google Sheets spreadsheet with specified sheets |
+| [Google Sheets Delete Column](block-integrations/google/sheets.md#google-sheets-delete-column) | Delete a column by header name or column letter |
+| [Google Sheets Delete Rows](block-integrations/google/sheets.md#google-sheets-delete-rows) | Delete specific rows from a Google Sheet by their row indices |
+| [Google Sheets Export Csv](block-integrations/google/sheets.md#google-sheets-export-csv) | Export a Google Sheet as CSV data |
+| [Google Sheets Filter Rows](block-integrations/google/sheets.md#google-sheets-filter-rows) | Filter rows in a Google Sheet based on a column condition |
+| [Google Sheets Find](block-integrations/google/sheets.md#google-sheets-find) | Find text in a Google Sheets spreadsheet |
+| [Google Sheets Find Replace](block-integrations/google/sheets.md#google-sheets-find-replace) | This block finds and replaces text in a Google Sheets spreadsheet |
+| [Google Sheets Format](block-integrations/google/sheets.md#google-sheets-format) | Format a range in a Google Sheet (sheet optional) |
+| [Google Sheets Get Column](block-integrations/google/sheets.md#google-sheets-get-column) | Extract all values from a specific column |
+| [Google Sheets Get Notes](block-integrations/google/sheets.md#google-sheets-get-notes) | Get notes from cells in a Google Sheet |
+| [Google Sheets Get Row](block-integrations/google/sheets.md#google-sheets-get-row) | Get a specific row by its index |
+| [Google Sheets Get Row Count](block-integrations/google/sheets.md#google-sheets-get-row-count) | Get row count and dimensions of a Google Sheet |
+| [Google Sheets Get Unique Values](block-integrations/google/sheets.md#google-sheets-get-unique-values) | Get unique values from a column |
+| [Google Sheets Import Csv](block-integrations/google/sheets.md#google-sheets-import-csv) | Import CSV data into a Google Sheet |
+| [Google Sheets Insert Row](block-integrations/google/sheets.md#google-sheets-insert-row) | Insert a single row at a specific position |
+| [Google Sheets List Named Ranges](block-integrations/google/sheets.md#google-sheets-list-named-ranges) | List all named ranges in a spreadsheet |
+| [Google Sheets Lookup Row](block-integrations/google/sheets.md#google-sheets-lookup-row) | Look up a row by finding a value in a specific column |
+| [Google Sheets Manage Sheet](block-integrations/google/sheets.md#google-sheets-manage-sheet) | Create, delete, or copy sheets (sheet optional) |
+| [Google Sheets Metadata](block-integrations/google/sheets.md#google-sheets-metadata) | This block retrieves metadata about a Google Sheets spreadsheet including sheet names and properties |
+| [Google Sheets Protect Range](block-integrations/google/sheets.md#google-sheets-protect-range) | Protect a cell range or entire sheet from editing |
+| [Google Sheets Read](block-integrations/google/sheets.md#google-sheets-read) | A block that reads data from a Google Sheets spreadsheet using A1 notation range selection |
+| [Google Sheets Remove Duplicates](block-integrations/google/sheets.md#google-sheets-remove-duplicates) | Remove duplicate rows based on specified columns |
+| [Google Sheets Set Public Access](block-integrations/google/sheets.md#google-sheets-set-public-access) | Make a Google Spreadsheet public or private |
+| [Google Sheets Share Spreadsheet](block-integrations/google/sheets.md#google-sheets-share-spreadsheet) | Share a Google Spreadsheet with users or get shareable link |
+| [Google Sheets Sort](block-integrations/google/sheets.md#google-sheets-sort) | Sort a Google Sheet by one or two columns |
+| [Google Sheets Update Cell](block-integrations/google/sheets.md#google-sheets-update-cell) | Update a single cell in a Google Sheets spreadsheet |
+| [Google Sheets Update Row](block-integrations/google/sheets.md#google-sheets-update-row) | Update a specific row by its index |
+| [Google Sheets Write](block-integrations/google/sheets.md#google-sheets-write) | A block that writes data to a Google Sheets spreadsheet at a specified A1 notation range |
+| [Keyword Suggestion Extractor](block-integrations/dataforseo/keyword_suggestions.md#keyword-suggestion-extractor) | Extract individual fields from a KeywordSuggestion object |
+| [Persist Information](block-integrations/data.md#persist-information) | Persist key-value information for the current user |
+| [Read Spreadsheet](block-integrations/data.md#read-spreadsheet) | Reads CSV and Excel files and outputs the data as a list of dictionaries and individual rows |
+| [Related Keyword Extractor](block-integrations/dataforseo/related_keywords.md#related-keyword-extractor) | Extract individual fields from a RelatedKeyword object |
+| [Retrieve Information](block-integrations/data.md#retrieve-information) | Retrieve key-value information for the current user |
+| [Screenshot Web Page](block-integrations/data.md#screenshot-web-page) | Takes a screenshot of a specified website using ScreenshotOne API |
## Text Processing
| Block Name | Description |
|------------|-------------|
-| [Code Extraction](text.md#code-extraction) | Extracts code blocks from text and identifies their programming languages |
-| [Combine Texts](text.md#combine-texts) | This block combines multiple input texts into a single output text |
-| [Countdown Timer](text.md#countdown-timer) | This block triggers after a specified duration |
-| [Extract Text Information](text.md#extract-text-information) | This block extracts the text from the given text using the pattern (regex) |
-| [Fill Text Template](text.md#fill-text-template) | This block formats the given texts using the format template |
-| [Get Current Date](text.md#get-current-date) | This block outputs the current date with an optional offset |
-| [Get Current Date And Time](text.md#get-current-date-and-time) | This block outputs the current date and time |
-| [Get Current Time](text.md#get-current-time) | This block outputs the current time |
-| [Match Text Pattern](text.md#match-text-pattern) | Matches text against a regex pattern and forwards data to positive or negative output based on the match |
-| [Text Decoder](text.md#text-decoder) | Decodes a string containing escape sequences into actual text |
-| [Text Replace](text.md#text-replace) | This block is used to replace a text with a new text |
-| [Text Split](text.md#text-split) | This block is used to split a text into a list of strings |
-| [Word Character Count](text.md#word-character-count) | Counts the number of words and characters in a given text |
+| [Code Extraction](block-integrations/text.md#code-extraction) | Extracts code blocks from text and identifies their programming languages |
+| [Combine Texts](block-integrations/text.md#combine-texts) | This block combines multiple input texts into a single output text |
+| [Countdown Timer](block-integrations/text.md#countdown-timer) | This block triggers after a specified duration |
+| [Extract Text Information](block-integrations/text.md#extract-text-information) | This block extracts the text from the given text using the pattern (regex) |
+| [Fill Text Template](block-integrations/text.md#fill-text-template) | This block formats the given texts using the format template |
+| [Get Current Date](block-integrations/text.md#get-current-date) | This block outputs the current date with an optional offset |
+| [Get Current Date And Time](block-integrations/text.md#get-current-date-and-time) | This block outputs the current date and time |
+| [Get Current Time](block-integrations/text.md#get-current-time) | This block outputs the current time |
+| [Match Text Pattern](block-integrations/text.md#match-text-pattern) | Matches text against a regex pattern and forwards data to positive or negative output based on the match |
+| [Text Decoder](block-integrations/text.md#text-decoder) | Decodes a string containing escape sequences into actual text |
+| [Text Replace](block-integrations/text.md#text-replace) | This block is used to replace a text with a new text |
+| [Text Split](block-integrations/text.md#text-split) | This block is used to split a text into a list of strings |
+| [Word Character Count](block-integrations/text.md#word-character-count) | Counts the number of words and characters in a given text |
## AI and Language Models
| Block Name | Description |
|------------|-------------|
-| [AI Ad Maker Video Creator](llm.md#ai-ad-maker-video-creator) | Creates an AI‑generated 30‑second advert (text + images) |
-| [AI Condition](llm.md#ai-condition) | Uses AI to evaluate natural language conditions and provide conditional outputs |
-| [AI Conversation](llm.md#ai-conversation) | A block that facilitates multi-turn conversations with a Large Language Model (LLM), maintaining context across message exchanges |
-| [AI Image Customizer](llm.md#ai-image-customizer) | Generate and edit custom images using Google's Nano-Banana model from Gemini 2 |
-| [AI Image Editor](llm.md#ai-image-editor) | Edit images using BlackForest Labs' Flux Kontext models |
-| [AI Image Generator](llm.md#ai-image-generator) | Generate images using various AI models through a unified interface |
-| [AI List Generator](llm.md#ai-list-generator) | A block that creates lists of items based on prompts using a Large Language Model (LLM), with optional source data for context |
-| [AI Music Generator](llm.md#ai-music-generator) | This block generates music using Meta's MusicGen model on Replicate |
-| [AI Screenshot To Video Ad](llm.md#ai-screenshot-to-video-ad) | Turns a screenshot into an engaging, avatar‑narrated video advert |
-| [AI Shortform Video Creator](llm.md#ai-shortform-video-creator) | Creates a shortform video using revid |
-| [AI Structured Response Generator](llm.md#ai-structured-response-generator) | A block that generates structured JSON responses using a Large Language Model (LLM), with schema validation and format enforcement |
-| [AI Text Generator](llm.md#ai-text-generator) | A block that produces text responses using a Large Language Model (LLM) based on customizable prompts and system instructions |
-| [AI Text Summarizer](llm.md#ai-text-summarizer) | A block that summarizes long texts using a Large Language Model (LLM), with configurable focus topics and summary styles |
-| [AI Video Generator](fal/ai_video_generator.md#ai-video-generator) | Generate videos using FAL AI models |
-| [Bannerbear Text Overlay](bannerbear/text_overlay.md#bannerbear-text-overlay) | Add text overlay to images using Bannerbear templates |
-| [Code Generation](llm.md#code-generation) | Generate or refactor code using OpenAI's Codex (Responses API) |
-| [Create Talking Avatar Video](llm.md#create-talking-avatar-video) | This block integrates with D-ID to create video clips and retrieve their URLs |
-| [Exa Answer](exa/answers.md#exa-answer) | Get an LLM answer to a question informed by Exa search results |
-| [Exa Create Enrichment](exa/websets_enrichment.md#exa-create-enrichment) | Create enrichments to extract additional structured data from webset items |
-| [Exa Create Research](exa/research.md#exa-create-research) | Create research task with optional waiting - explores web and synthesizes findings with citations |
-| [Ideogram Model](llm.md#ideogram-model) | This block runs Ideogram models with both simple and advanced settings |
-| [Jina Chunking](jina/chunking.md#jina-chunking) | Chunks texts using Jina AI's segmentation service |
-| [Jina Embedding](jina/embeddings.md#jina-embedding) | Generates embeddings using Jina AI |
-| [Perplexity](llm.md#perplexity) | Query Perplexity's sonar models with real-time web search capabilities and receive annotated responses with source citations |
-| [Replicate Flux Advanced Model](replicate/flux_advanced.md#replicate-flux-advanced-model) | This block runs Flux models on Replicate with advanced settings |
-| [Replicate Model](replicate/replicate_block.md#replicate-model) | Run Replicate models synchronously |
-| [Smart Decision Maker](llm.md#smart-decision-maker) | Uses AI to intelligently decide what tool to use |
-| [Stagehand Act](stagehand/blocks.md#stagehand-act) | Interact with a web page by performing actions on a web page |
-| [Stagehand Extract](stagehand/blocks.md#stagehand-extract) | Extract structured data from a webpage |
-| [Stagehand Observe](stagehand/blocks.md#stagehand-observe) | Find suggested actions for your workflows |
-| [Unreal Text To Speech](llm.md#unreal-text-to-speech) | Converts text to speech using the Unreal Speech API |
+| [AI Ad Maker Video Creator](block-integrations/llm.md#ai-ad-maker-video-creator) | Creates an AI‑generated 30‑second advert (text + images) |
+| [AI Condition](block-integrations/llm.md#ai-condition) | Uses AI to evaluate natural language conditions and provide conditional outputs |
+| [AI Conversation](block-integrations/llm.md#ai-conversation) | A block that facilitates multi-turn conversations with a Large Language Model (LLM), maintaining context across message exchanges |
+| [AI Image Customizer](block-integrations/llm.md#ai-image-customizer) | Generate and edit custom images using Google's Nano-Banana model from Gemini 2 |
+| [AI Image Editor](block-integrations/llm.md#ai-image-editor) | Edit images using BlackForest Labs' Flux Kontext models |
+| [AI Image Generator](block-integrations/llm.md#ai-image-generator) | Generate images using various AI models through a unified interface |
+| [AI List Generator](block-integrations/llm.md#ai-list-generator) | A block that creates lists of items based on prompts using a Large Language Model (LLM), with optional source data for context |
+| [AI Music Generator](block-integrations/llm.md#ai-music-generator) | This block generates music using Meta's MusicGen model on Replicate |
+| [AI Screenshot To Video Ad](block-integrations/llm.md#ai-screenshot-to-video-ad) | Turns a screenshot into an engaging, avatar‑narrated video advert |
+| [AI Shortform Video Creator](block-integrations/llm.md#ai-shortform-video-creator) | Creates a shortform video using revid |
+| [AI Structured Response Generator](block-integrations/llm.md#ai-structured-response-generator) | A block that generates structured JSON responses using a Large Language Model (LLM), with schema validation and format enforcement |
+| [AI Text Generator](block-integrations/llm.md#ai-text-generator) | A block that produces text responses using a Large Language Model (LLM) based on customizable prompts and system instructions |
+| [AI Text Summarizer](block-integrations/llm.md#ai-text-summarizer) | A block that summarizes long texts using a Large Language Model (LLM), with configurable focus topics and summary styles |
+| [AI Video Generator](block-integrations/fal/ai_video_generator.md#ai-video-generator) | Generate videos using FAL AI models |
+| [Bannerbear Text Overlay](block-integrations/bannerbear/text_overlay.md#bannerbear-text-overlay) | Add text overlay to images using Bannerbear templates |
+| [Claude Code](block-integrations/llm.md#claude-code) | Execute tasks using Claude Code in an E2B sandbox |
+| [Code Generation](block-integrations/llm.md#code-generation) | Generate or refactor code using OpenAI's Codex (Responses API) |
+| [Create Talking Avatar Video](block-integrations/llm.md#create-talking-avatar-video) | This block integrates with D-ID to create video clips and retrieve their URLs |
+| [Exa Answer](block-integrations/exa/answers.md#exa-answer) | Get an LLM answer to a question informed by Exa search results |
+| [Exa Create Enrichment](block-integrations/exa/websets_enrichment.md#exa-create-enrichment) | Create enrichments to extract additional structured data from webset items |
+| [Exa Create Research](block-integrations/exa/research.md#exa-create-research) | Create research task with optional waiting - explores web and synthesizes findings with citations |
+| [Ideogram Model](block-integrations/llm.md#ideogram-model) | This block runs Ideogram models with both simple and advanced settings |
+| [Jina Chunking](block-integrations/jina/chunking.md#jina-chunking) | Chunks texts using Jina AI's segmentation service |
+| [Jina Embedding](block-integrations/jina/embeddings.md#jina-embedding) | Generates embeddings using Jina AI |
+| [Perplexity](block-integrations/llm.md#perplexity) | Query Perplexity's sonar models with real-time web search capabilities and receive annotated responses with source citations |
+| [Replicate Flux Advanced Model](block-integrations/replicate/flux_advanced.md#replicate-flux-advanced-model) | This block runs Flux models on Replicate with advanced settings |
+| [Replicate Model](block-integrations/replicate/replicate_block.md#replicate-model) | Run Replicate models synchronously |
+| [Smart Decision Maker](block-integrations/llm.md#smart-decision-maker) | Uses AI to intelligently decide what tool to use |
+| [Stagehand Act](block-integrations/stagehand/blocks.md#stagehand-act) | Interact with a web page by performing actions on a web page |
+| [Stagehand Extract](block-integrations/stagehand/blocks.md#stagehand-extract) | Extract structured data from a webpage |
+| [Stagehand Observe](block-integrations/stagehand/blocks.md#stagehand-observe) | Find suggested actions for your workflows |
+| [Unreal Text To Speech](block-integrations/llm.md#unreal-text-to-speech) | Converts text to speech using the Unreal Speech API |
## Search and Information Retrieval
| Block Name | Description |
|------------|-------------|
-| [Ask Wolfram](wolfram/llm_api.md#ask-wolfram) | Ask Wolfram Alpha a question |
-| [Exa Bulk Webset Items](exa/websets_items.md#exa-bulk-webset-items) | Get all items from a webset in bulk (with configurable limits) |
-| [Exa Cancel Enrichment](exa/websets_enrichment.md#exa-cancel-enrichment) | Cancel a running enrichment operation |
-| [Exa Cancel Webset](exa/websets.md#exa-cancel-webset) | Cancel all operations being performed on a Webset |
-| [Exa Cancel Webset Search](exa/websets_search.md#exa-cancel-webset-search) | Cancel a running webset search |
-| [Exa Contents](exa/contents.md#exa-contents) | Retrieves document contents using Exa's contents API |
-| [Exa Create Monitor](exa/websets_monitor.md#exa-create-monitor) | Create automated monitors to keep websets updated with fresh data on a schedule |
-| [Exa Create Or Find Webset](exa/websets.md#exa-create-or-find-webset) | Create a new webset or return existing one by external_id (idempotent operation) |
-| [Exa Create Webset](exa/websets.md#exa-create-webset) | Create a new Exa Webset for persistent web search collections with optional waiting for initial results |
-| [Exa Create Webset Search](exa/websets_search.md#exa-create-webset-search) | Add a new search to an existing webset to find more items |
-| [Exa Delete Enrichment](exa/websets_enrichment.md#exa-delete-enrichment) | Delete an enrichment from a webset |
-| [Exa Delete Monitor](exa/websets_monitor.md#exa-delete-monitor) | Delete a monitor from a webset |
-| [Exa Delete Webset](exa/websets.md#exa-delete-webset) | Delete a Webset and all its items |
-| [Exa Delete Webset Item](exa/websets_items.md#exa-delete-webset-item) | Delete a specific item from a webset |
-| [Exa Find Or Create Search](exa/websets_search.md#exa-find-or-create-search) | Find existing search by query or create new - prevents duplicate searches in workflows |
-| [Exa Find Similar](exa/similar.md#exa-find-similar) | Finds similar links using Exa's findSimilar API |
-| [Exa Get Enrichment](exa/websets_enrichment.md#exa-get-enrichment) | Get the status and details of a webset enrichment |
-| [Exa Get Monitor](exa/websets_monitor.md#exa-get-monitor) | Get the details and status of a webset monitor |
-| [Exa Get Research](exa/research.md#exa-get-research) | Get status and results of a research task |
-| [Exa Get Webset](exa/websets.md#exa-get-webset) | Retrieve a Webset by ID or external ID |
-| [Exa Get Webset Item](exa/websets_items.md#exa-get-webset-item) | Get a specific item from a webset by its ID |
-| [Exa Get Webset Search](exa/websets_search.md#exa-get-webset-search) | Get the status and details of a webset search |
-| [Exa List Monitors](exa/websets_monitor.md#exa-list-monitors) | List all monitors with optional webset filtering |
-| [Exa List Research](exa/research.md#exa-list-research) | List all research tasks with pagination support |
-| [Exa List Webset Items](exa/websets_items.md#exa-list-webset-items) | List items in a webset with pagination support |
-| [Exa List Websets](exa/websets.md#exa-list-websets) | List all Websets with pagination support |
-| [Exa Preview Webset](exa/websets.md#exa-preview-webset) | Preview how a search query will be interpreted before creating a webset |
-| [Exa Search](exa/search.md#exa-search) | Searches the web using Exa's advanced search API |
-| [Exa Update Enrichment](exa/websets_enrichment.md#exa-update-enrichment) | Update an existing enrichment configuration |
-| [Exa Update Monitor](exa/websets_monitor.md#exa-update-monitor) | Update a monitor's status, schedule, or metadata |
-| [Exa Update Webset](exa/websets.md#exa-update-webset) | Update metadata for an existing Webset |
-| [Exa Wait For Enrichment](exa/websets_polling.md#exa-wait-for-enrichment) | Wait for a webset enrichment to complete with progress tracking |
-| [Exa Wait For Research](exa/research.md#exa-wait-for-research) | Wait for a research task to complete with configurable timeout |
-| [Exa Wait For Search](exa/websets_polling.md#exa-wait-for-search) | Wait for a specific webset search to complete with progress tracking |
-| [Exa Wait For Webset](exa/websets_polling.md#exa-wait-for-webset) | Wait for a webset to reach a specific status with progress tracking |
-| [Exa Webset Items Summary](exa/websets_items.md#exa-webset-items-summary) | Get a summary of webset items without retrieving all data |
-| [Exa Webset Status](exa/websets.md#exa-webset-status) | Get a quick status overview of a webset |
-| [Exa Webset Summary](exa/websets.md#exa-webset-summary) | Get a comprehensive summary of a webset with samples and statistics |
-| [Extract Website Content](jina/search.md#extract-website-content) | This block scrapes the content from the given web URL |
-| [Fact Checker](jina/fact_checker.md#fact-checker) | This block checks the factuality of a given statement using Jina AI's Grounding API |
-| [Firecrawl Crawl](firecrawl/crawl.md#firecrawl-crawl) | Firecrawl crawls websites to extract comprehensive data while bypassing blockers |
-| [Firecrawl Extract](firecrawl/extract.md#firecrawl-extract) | Firecrawl crawls websites to extract comprehensive data while bypassing blockers |
-| [Firecrawl Map Website](firecrawl/map.md#firecrawl-map-website) | Firecrawl maps a website to extract all the links |
-| [Firecrawl Scrape](firecrawl/scrape.md#firecrawl-scrape) | Firecrawl scrapes a website to extract comprehensive data while bypassing blockers |
-| [Firecrawl Search](firecrawl/search.md#firecrawl-search) | Firecrawl searches the web for the given query |
-| [Get Person Detail](apollo/person.md#get-person-detail) | Get detailed person data with Apollo API, including email reveal |
-| [Get Wikipedia Summary](search.md#get-wikipedia-summary) | This block fetches the summary of a given topic from Wikipedia |
-| [Google Maps Search](search.md#google-maps-search) | This block searches for local businesses using Google Maps API |
-| [Search Organizations](apollo/organization.md#search-organizations) | Search for organizations in Apollo |
-| [Search People](apollo/people.md#search-people) | Search for people in Apollo |
-| [Search The Web](jina/search.md#search-the-web) | This block searches the internet for the given search query |
-| [Validate Emails](zerobounce/validate_emails.md#validate-emails) | Validate emails |
+| [Ask Wolfram](block-integrations/wolfram/llm_api.md#ask-wolfram) | Ask Wolfram Alpha a question |
+| [Exa Bulk Webset Items](block-integrations/exa/websets_items.md#exa-bulk-webset-items) | Get all items from a webset in bulk (with configurable limits) |
+| [Exa Cancel Enrichment](block-integrations/exa/websets_enrichment.md#exa-cancel-enrichment) | Cancel a running enrichment operation |
+| [Exa Cancel Webset](block-integrations/exa/websets.md#exa-cancel-webset) | Cancel all operations being performed on a Webset |
+| [Exa Cancel Webset Search](block-integrations/exa/websets_search.md#exa-cancel-webset-search) | Cancel a running webset search |
+| [Exa Contents](block-integrations/exa/contents.md#exa-contents) | Retrieves document contents using Exa's contents API |
+| [Exa Create Monitor](block-integrations/exa/websets_monitor.md#exa-create-monitor) | Create automated monitors to keep websets updated with fresh data on a schedule |
+| [Exa Create Or Find Webset](block-integrations/exa/websets.md#exa-create-or-find-webset) | Create a new webset or return existing one by external_id (idempotent operation) |
+| [Exa Create Webset](block-integrations/exa/websets.md#exa-create-webset) | Create a new Exa Webset for persistent web search collections with optional waiting for initial results |
+| [Exa Create Webset Search](block-integrations/exa/websets_search.md#exa-create-webset-search) | Add a new search to an existing webset to find more items |
+| [Exa Delete Enrichment](block-integrations/exa/websets_enrichment.md#exa-delete-enrichment) | Delete an enrichment from a webset |
+| [Exa Delete Monitor](block-integrations/exa/websets_monitor.md#exa-delete-monitor) | Delete a monitor from a webset |
+| [Exa Delete Webset](block-integrations/exa/websets.md#exa-delete-webset) | Delete a Webset and all its items |
+| [Exa Delete Webset Item](block-integrations/exa/websets_items.md#exa-delete-webset-item) | Delete a specific item from a webset |
+| [Exa Find Or Create Search](block-integrations/exa/websets_search.md#exa-find-or-create-search) | Find existing search by query or create new - prevents duplicate searches in workflows |
+| [Exa Find Similar](block-integrations/exa/similar.md#exa-find-similar) | Finds similar links using Exa's findSimilar API |
+| [Exa Get Enrichment](block-integrations/exa/websets_enrichment.md#exa-get-enrichment) | Get the status and details of a webset enrichment |
+| [Exa Get Monitor](block-integrations/exa/websets_monitor.md#exa-get-monitor) | Get the details and status of a webset monitor |
+| [Exa Get Research](block-integrations/exa/research.md#exa-get-research) | Get status and results of a research task |
+| [Exa Get Webset](block-integrations/exa/websets.md#exa-get-webset) | Retrieve a Webset by ID or external ID |
+| [Exa Get Webset Item](block-integrations/exa/websets_items.md#exa-get-webset-item) | Get a specific item from a webset by its ID |
+| [Exa Get Webset Search](block-integrations/exa/websets_search.md#exa-get-webset-search) | Get the status and details of a webset search |
+| [Exa List Monitors](block-integrations/exa/websets_monitor.md#exa-list-monitors) | List all monitors with optional webset filtering |
+| [Exa List Research](block-integrations/exa/research.md#exa-list-research) | List all research tasks with pagination support |
+| [Exa List Webset Items](block-integrations/exa/websets_items.md#exa-list-webset-items) | List items in a webset with pagination support |
+| [Exa List Websets](block-integrations/exa/websets.md#exa-list-websets) | List all Websets with pagination support |
+| [Exa Preview Webset](block-integrations/exa/websets.md#exa-preview-webset) | Preview how a search query will be interpreted before creating a webset |
+| [Exa Search](block-integrations/exa/search.md#exa-search) | Searches the web using Exa's advanced search API |
+| [Exa Update Enrichment](block-integrations/exa/websets_enrichment.md#exa-update-enrichment) | Update an existing enrichment configuration |
+| [Exa Update Monitor](block-integrations/exa/websets_monitor.md#exa-update-monitor) | Update a monitor's status, schedule, or metadata |
+| [Exa Update Webset](block-integrations/exa/websets.md#exa-update-webset) | Update metadata for an existing Webset |
+| [Exa Wait For Enrichment](block-integrations/exa/websets_polling.md#exa-wait-for-enrichment) | Wait for a webset enrichment to complete with progress tracking |
+| [Exa Wait For Research](block-integrations/exa/research.md#exa-wait-for-research) | Wait for a research task to complete with configurable timeout |
+| [Exa Wait For Search](block-integrations/exa/websets_polling.md#exa-wait-for-search) | Wait for a specific webset search to complete with progress tracking |
+| [Exa Wait For Webset](block-integrations/exa/websets_polling.md#exa-wait-for-webset) | Wait for a webset to reach a specific status with progress tracking |
+| [Exa Webset Items Summary](block-integrations/exa/websets_items.md#exa-webset-items-summary) | Get a summary of webset items without retrieving all data |
+| [Exa Webset Status](block-integrations/exa/websets.md#exa-webset-status) | Get a quick status overview of a webset |
+| [Exa Webset Summary](block-integrations/exa/websets.md#exa-webset-summary) | Get a comprehensive summary of a webset with samples and statistics |
+| [Extract Website Content](block-integrations/jina/search.md#extract-website-content) | This block scrapes the content from the given web URL |
+| [Fact Checker](block-integrations/jina/fact_checker.md#fact-checker) | This block checks the factuality of a given statement using Jina AI's Grounding API |
+| [Firecrawl Crawl](block-integrations/firecrawl/crawl.md#firecrawl-crawl) | Firecrawl crawls websites to extract comprehensive data while bypassing blockers |
+| [Firecrawl Extract](block-integrations/firecrawl/extract.md#firecrawl-extract) | Firecrawl crawls websites to extract comprehensive data while bypassing blockers |
+| [Firecrawl Map Website](block-integrations/firecrawl/map.md#firecrawl-map-website) | Firecrawl maps a website to extract all the links |
+| [Firecrawl Scrape](block-integrations/firecrawl/scrape.md#firecrawl-scrape) | Firecrawl scrapes a website to extract comprehensive data while bypassing blockers |
+| [Firecrawl Search](block-integrations/firecrawl/search.md#firecrawl-search) | Firecrawl searches the web for the given query |
+| [Get Person Detail](block-integrations/apollo/person.md#get-person-detail) | Get detailed person data with Apollo API, including email reveal |
+| [Get Wikipedia Summary](block-integrations/search.md#get-wikipedia-summary) | This block fetches the summary of a given topic from Wikipedia |
+| [Google Maps Search](block-integrations/search.md#google-maps-search) | This block searches for local businesses using Google Maps API |
+| [Search Organizations](block-integrations/apollo/organization.md#search-organizations) | Search for organizations in Apollo |
+| [Search People](block-integrations/apollo/people.md#search-people) | Search for people in Apollo |
+| [Search The Web](block-integrations/jina/search.md#search-the-web) | This block searches the internet for the given search query |
+| [Validate Emails](block-integrations/zerobounce/validate_emails.md#validate-emails) | Validate emails |
## Social Media and Content
| Block Name | Description |
|------------|-------------|
-| [Create Discord Thread](discord/bot_blocks.md#create-discord-thread) | Creates a new thread in a Discord channel |
-| [Create Reddit Post](misc.md#create-reddit-post) | Create a new post on a subreddit |
-| [Delete Reddit Comment](misc.md#delete-reddit-comment) | Delete a Reddit comment that you own |
-| [Delete Reddit Post](misc.md#delete-reddit-post) | Delete a Reddit post that you own |
-| [Discord Channel Info](discord/bot_blocks.md#discord-channel-info) | Resolves Discord channel names to IDs and vice versa |
-| [Discord Get Current User](discord/oauth_blocks.md#discord-get-current-user) | Gets information about the currently authenticated Discord user using OAuth2 credentials |
-| [Discord User Info](discord/bot_blocks.md#discord-user-info) | Gets information about a Discord user by their ID |
-| [Edit Reddit Post](misc.md#edit-reddit-post) | Edit the body text of an existing Reddit post that you own |
-| [Get Linkedin Profile](enrichlayer/linkedin.md#get-linkedin-profile) | Fetch LinkedIn profile data using Enrichlayer |
-| [Get Linkedin Profile Picture](enrichlayer/linkedin.md#get-linkedin-profile-picture) | Get LinkedIn profile pictures using Enrichlayer |
-| [Get Reddit Comment](misc.md#get-reddit-comment) | Get details about a specific Reddit comment by its ID |
-| [Get Reddit Comment Replies](misc.md#get-reddit-comment-replies) | Get replies to a specific Reddit comment |
-| [Get Reddit Inbox](misc.md#get-reddit-inbox) | Get messages, mentions, and comment replies from your Reddit inbox |
-| [Get Reddit Post](misc.md#get-reddit-post) | Get detailed information about a specific Reddit post by its ID |
-| [Get Reddit Post Comments](misc.md#get-reddit-post-comments) | Get top-level comments on a Reddit post |
-| [Get Reddit Posts](misc.md#get-reddit-posts) | This block fetches Reddit posts from a defined subreddit name |
-| [Get Reddit User Info](misc.md#get-reddit-user-info) | Get information about a Reddit user including karma, account age, and verification status |
-| [Get Subreddit Flairs](misc.md#get-subreddit-flairs) | Get available link flair options for a subreddit |
-| [Get Subreddit Info](misc.md#get-subreddit-info) | Get information about a subreddit including subscriber count, description, and rules |
-| [Get Subreddit Rules](misc.md#get-subreddit-rules) | Get the rules for a subreddit to ensure compliance before posting |
-| [Get User Posts](misc.md#get-user-posts) | Fetch posts by a specific Reddit user |
-| [Linkedin Person Lookup](enrichlayer/linkedin.md#linkedin-person-lookup) | Look up LinkedIn profiles by person information using Enrichlayer |
-| [Linkedin Role Lookup](enrichlayer/linkedin.md#linkedin-role-lookup) | Look up LinkedIn profiles by role in a company using Enrichlayer |
-| [Post Reddit Comment](misc.md#post-reddit-comment) | This block posts a Reddit comment on a specified Reddit post |
-| [Post To Bluesky](ayrshare/post_to_bluesky.md#post-to-bluesky) | Post to Bluesky using Ayrshare |
-| [Post To Facebook](ayrshare/post_to_facebook.md#post-to-facebook) | Post to Facebook using Ayrshare |
-| [Post To GMB](ayrshare/post_to_gmb.md#post-to-gmb) | Post to Google My Business using Ayrshare |
-| [Post To Instagram](ayrshare/post_to_instagram.md#post-to-instagram) | Post to Instagram using Ayrshare |
-| [Post To Linked In](ayrshare/post_to_linkedin.md#post-to-linked-in) | Post to LinkedIn using Ayrshare |
-| [Post To Pinterest](ayrshare/post_to_pinterest.md#post-to-pinterest) | Post to Pinterest using Ayrshare |
-| [Post To Reddit](ayrshare/post_to_reddit.md#post-to-reddit) | Post to Reddit using Ayrshare |
-| [Post To Snapchat](ayrshare/post_to_snapchat.md#post-to-snapchat) | Post to Snapchat using Ayrshare |
-| [Post To Telegram](ayrshare/post_to_telegram.md#post-to-telegram) | Post to Telegram using Ayrshare |
-| [Post To Threads](ayrshare/post_to_threads.md#post-to-threads) | Post to Threads using Ayrshare |
-| [Post To Tik Tok](ayrshare/post_to_tiktok.md#post-to-tik-tok) | Post to TikTok using Ayrshare |
-| [Post To X](ayrshare/post_to_x.md#post-to-x) | Post to X / Twitter using Ayrshare |
-| [Post To You Tube](ayrshare/post_to_youtube.md#post-to-you-tube) | Post to YouTube using Ayrshare |
-| [Publish To Medium](misc.md#publish-to-medium) | Publishes a post to Medium |
-| [Read Discord Messages](discord/bot_blocks.md#read-discord-messages) | Reads messages from a Discord channel using a bot token |
-| [Reddit Get My Posts](misc.md#reddit-get-my-posts) | Fetch posts created by the authenticated Reddit user (you) |
-| [Reply To Discord Message](discord/bot_blocks.md#reply-to-discord-message) | Replies to a specific Discord message |
-| [Reply To Reddit Comment](misc.md#reply-to-reddit-comment) | Reply to a specific Reddit comment |
-| [Search Reddit](misc.md#search-reddit) | Search Reddit for posts matching a query |
-| [Send Discord DM](discord/bot_blocks.md#send-discord-dm) | Sends a direct message to a Discord user using their user ID |
-| [Send Discord Embed](discord/bot_blocks.md#send-discord-embed) | Sends a rich embed message to a Discord channel |
-| [Send Discord File](discord/bot_blocks.md#send-discord-file) | Sends a file attachment to a Discord channel |
-| [Send Discord Message](discord/bot_blocks.md#send-discord-message) | Sends a message to a Discord channel using a bot token |
-| [Send Reddit Message](misc.md#send-reddit-message) | Send a private message (DM) to a Reddit user |
-| [Transcribe Youtube Video](misc.md#transcribe-youtube-video) | Transcribes a YouTube video using a proxy |
-| [Twitter Add List Member](twitter/list_members.md#twitter-add-list-member) | This block adds a specified user to a Twitter List owned by the authenticated user |
-| [Twitter Bookmark Tweet](twitter/bookmark.md#twitter-bookmark-tweet) | This block bookmarks a tweet on Twitter |
-| [Twitter Create List](twitter/manage_lists.md#twitter-create-list) | This block creates a new Twitter List for the authenticated user |
-| [Twitter Delete List](twitter/manage_lists.md#twitter-delete-list) | This block deletes a specified Twitter List owned by the authenticated user |
-| [Twitter Delete Tweet](twitter/manage.md#twitter-delete-tweet) | This block deletes a tweet on Twitter |
-| [Twitter Follow List](twitter/list_follows.md#twitter-follow-list) | This block follows a specified Twitter list for the authenticated user |
-| [Twitter Follow User](twitter/follows.md#twitter-follow-user) | This block follows a specified Twitter user |
-| [Twitter Get Blocked Users](twitter/blocks.md#twitter-get-blocked-users) | This block retrieves a list of users blocked by the authenticating user |
-| [Twitter Get Bookmarked Tweets](twitter/bookmark.md#twitter-get-bookmarked-tweets) | This block retrieves bookmarked tweets from Twitter |
-| [Twitter Get Followers](twitter/follows.md#twitter-get-followers) | This block retrieves followers of a specified Twitter user |
-| [Twitter Get Following](twitter/follows.md#twitter-get-following) | This block retrieves the users that a specified Twitter user is following |
-| [Twitter Get Home Timeline](twitter/timeline.md#twitter-get-home-timeline) | This block retrieves the authenticated user's home timeline |
-| [Twitter Get Liked Tweets](twitter/like.md#twitter-get-liked-tweets) | This block gets information about tweets liked by a user |
-| [Twitter Get Liking Users](twitter/like.md#twitter-get-liking-users) | This block gets information about users who liked a tweet |
-| [Twitter Get List](twitter/list_lookup.md#twitter-get-list) | This block retrieves information about a specified Twitter List |
-| [Twitter Get List Members](twitter/list_members.md#twitter-get-list-members) | This block retrieves the members of a specified Twitter List |
-| [Twitter Get List Memberships](twitter/list_members.md#twitter-get-list-memberships) | This block retrieves all Lists that a specified user is a member of |
-| [Twitter Get List Tweets](twitter/list_tweets_lookup.md#twitter-get-list-tweets) | This block retrieves tweets from a specified Twitter list |
-| [Twitter Get Muted Users](twitter/mutes.md#twitter-get-muted-users) | This block gets a list of users muted by the authenticating user |
-| [Twitter Get Owned Lists](twitter/list_lookup.md#twitter-get-owned-lists) | This block retrieves all Lists owned by a specified Twitter user |
-| [Twitter Get Pinned Lists](twitter/pinned_lists.md#twitter-get-pinned-lists) | This block returns the Lists pinned by the authenticated user |
-| [Twitter Get Quote Tweets](twitter/quote.md#twitter-get-quote-tweets) | This block gets quote tweets for a specific tweet |
-| [Twitter Get Retweeters](twitter/retweet.md#twitter-get-retweeters) | This block gets information about who has retweeted a tweet |
-| [Twitter Get Space Buyers](twitter/spaces_lookup.md#twitter-get-space-buyers) | This block retrieves a list of users who purchased tickets to a Twitter Space |
-| [Twitter Get Space By Id](twitter/spaces_lookup.md#twitter-get-space-by-id) | This block retrieves information about a single Twitter Space |
-| [Twitter Get Space Tweets](twitter/spaces_lookup.md#twitter-get-space-tweets) | This block retrieves tweets shared in a Twitter Space |
-| [Twitter Get Spaces](twitter/spaces_lookup.md#twitter-get-spaces) | This block retrieves information about multiple Twitter Spaces |
-| [Twitter Get Tweet](twitter/tweet_lookup.md#twitter-get-tweet) | This block retrieves information about a specific Tweet |
-| [Twitter Get Tweets](twitter/tweet_lookup.md#twitter-get-tweets) | This block retrieves information about multiple Tweets |
-| [Twitter Get User](twitter/user_lookup.md#twitter-get-user) | This block retrieves information about a specified Twitter user |
-| [Twitter Get User Mentions](twitter/timeline.md#twitter-get-user-mentions) | This block retrieves Tweets mentioning a specific user |
-| [Twitter Get User Tweets](twitter/timeline.md#twitter-get-user-tweets) | This block retrieves Tweets composed by a single user |
-| [Twitter Get Users](twitter/user_lookup.md#twitter-get-users) | This block retrieves information about multiple Twitter users |
-| [Twitter Hide Reply](twitter/hide.md#twitter-hide-reply) | This block hides a reply to a tweet |
-| [Twitter Like Tweet](twitter/like.md#twitter-like-tweet) | This block likes a tweet |
-| [Twitter Mute User](twitter/mutes.md#twitter-mute-user) | This block mutes a specified Twitter user |
-| [Twitter Pin List](twitter/pinned_lists.md#twitter-pin-list) | This block allows the authenticated user to pin a specified List |
-| [Twitter Post Tweet](twitter/manage.md#twitter-post-tweet) | This block posts a tweet on Twitter |
-| [Twitter Remove Bookmark Tweet](twitter/bookmark.md#twitter-remove-bookmark-tweet) | This block removes a bookmark from a tweet on Twitter |
-| [Twitter Remove List Member](twitter/list_members.md#twitter-remove-list-member) | This block removes a specified user from a Twitter List owned by the authenticated user |
-| [Twitter Remove Retweet](twitter/retweet.md#twitter-remove-retweet) | This block removes a retweet on Twitter |
-| [Twitter Retweet](twitter/retweet.md#twitter-retweet) | This block retweets a tweet on Twitter |
-| [Twitter Search Recent Tweets](twitter/manage.md#twitter-search-recent-tweets) | This block searches all public Tweets in Twitter history |
-| [Twitter Search Spaces](twitter/search_spaces.md#twitter-search-spaces) | This block searches for Twitter Spaces based on specified terms |
-| [Twitter Unfollow List](twitter/list_follows.md#twitter-unfollow-list) | This block unfollows a specified Twitter list for the authenticated user |
-| [Twitter Unfollow User](twitter/follows.md#twitter-unfollow-user) | This block unfollows a specified Twitter user |
-| [Twitter Unhide Reply](twitter/hide.md#twitter-unhide-reply) | This block unhides a reply to a tweet |
-| [Twitter Unlike Tweet](twitter/like.md#twitter-unlike-tweet) | This block unlikes a tweet |
-| [Twitter Unmute User](twitter/mutes.md#twitter-unmute-user) | This block unmutes a specified Twitter user |
-| [Twitter Unpin List](twitter/pinned_lists.md#twitter-unpin-list) | This block allows the authenticated user to unpin a specified List |
-| [Twitter Update List](twitter/manage_lists.md#twitter-update-list) | This block updates a specified Twitter List owned by the authenticated user |
+| [Create Discord Thread](block-integrations/discord/bot_blocks.md#create-discord-thread) | Creates a new thread in a Discord channel |
+| [Create Reddit Post](block-integrations/misc.md#create-reddit-post) | Create a new post on a subreddit |
+| [Delete Reddit Comment](block-integrations/misc.md#delete-reddit-comment) | Delete a Reddit comment that you own |
+| [Delete Reddit Post](block-integrations/misc.md#delete-reddit-post) | Delete a Reddit post that you own |
+| [Discord Channel Info](block-integrations/discord/bot_blocks.md#discord-channel-info) | Resolves Discord channel names to IDs and vice versa |
+| [Discord Get Current User](block-integrations/discord/oauth_blocks.md#discord-get-current-user) | Gets information about the currently authenticated Discord user using OAuth2 credentials |
+| [Discord User Info](block-integrations/discord/bot_blocks.md#discord-user-info) | Gets information about a Discord user by their ID |
+| [Edit Reddit Post](block-integrations/misc.md#edit-reddit-post) | Edit the body text of an existing Reddit post that you own |
+| [Get Linkedin Profile](block-integrations/enrichlayer/linkedin.md#get-linkedin-profile) | Fetch LinkedIn profile data using Enrichlayer |
+| [Get Linkedin Profile Picture](block-integrations/enrichlayer/linkedin.md#get-linkedin-profile-picture) | Get LinkedIn profile pictures using Enrichlayer |
+| [Get Reddit Comment](block-integrations/misc.md#get-reddit-comment) | Get details about a specific Reddit comment by its ID |
+| [Get Reddit Comment Replies](block-integrations/misc.md#get-reddit-comment-replies) | Get replies to a specific Reddit comment |
+| [Get Reddit Inbox](block-integrations/misc.md#get-reddit-inbox) | Get messages, mentions, and comment replies from your Reddit inbox |
+| [Get Reddit Post](block-integrations/misc.md#get-reddit-post) | Get detailed information about a specific Reddit post by its ID |
+| [Get Reddit Post Comments](block-integrations/misc.md#get-reddit-post-comments) | Get top-level comments on a Reddit post |
+| [Get Reddit Posts](block-integrations/misc.md#get-reddit-posts) | This block fetches Reddit posts from a defined subreddit name |
+| [Get Reddit User Info](block-integrations/misc.md#get-reddit-user-info) | Get information about a Reddit user including karma, account age, and verification status |
+| [Get Subreddit Flairs](block-integrations/misc.md#get-subreddit-flairs) | Get available link flair options for a subreddit |
+| [Get Subreddit Info](block-integrations/misc.md#get-subreddit-info) | Get information about a subreddit including subscriber count, description, and rules |
+| [Get Subreddit Rules](block-integrations/misc.md#get-subreddit-rules) | Get the rules for a subreddit to ensure compliance before posting |
+| [Get User Posts](block-integrations/misc.md#get-user-posts) | Fetch posts by a specific Reddit user |
+| [Linkedin Person Lookup](block-integrations/enrichlayer/linkedin.md#linkedin-person-lookup) | Look up LinkedIn profiles by person information using Enrichlayer |
+| [Linkedin Role Lookup](block-integrations/enrichlayer/linkedin.md#linkedin-role-lookup) | Look up LinkedIn profiles by role in a company using Enrichlayer |
+| [Post Reddit Comment](block-integrations/misc.md#post-reddit-comment) | This block posts a Reddit comment on a specified Reddit post |
+| [Post To Bluesky](block-integrations/ayrshare/post_to_bluesky.md#post-to-bluesky) | Post to Bluesky using Ayrshare |
+| [Post To Facebook](block-integrations/ayrshare/post_to_facebook.md#post-to-facebook) | Post to Facebook using Ayrshare |
+| [Post To GMB](block-integrations/ayrshare/post_to_gmb.md#post-to-gmb) | Post to Google My Business using Ayrshare |
+| [Post To Instagram](block-integrations/ayrshare/post_to_instagram.md#post-to-instagram) | Post to Instagram using Ayrshare |
+| [Post To Linked In](block-integrations/ayrshare/post_to_linkedin.md#post-to-linked-in) | Post to LinkedIn using Ayrshare |
+| [Post To Pinterest](block-integrations/ayrshare/post_to_pinterest.md#post-to-pinterest) | Post to Pinterest using Ayrshare |
+| [Post To Reddit](block-integrations/ayrshare/post_to_reddit.md#post-to-reddit) | Post to Reddit using Ayrshare |
+| [Post To Snapchat](block-integrations/ayrshare/post_to_snapchat.md#post-to-snapchat) | Post to Snapchat using Ayrshare |
+| [Post To Telegram](block-integrations/ayrshare/post_to_telegram.md#post-to-telegram) | Post to Telegram using Ayrshare |
+| [Post To Threads](block-integrations/ayrshare/post_to_threads.md#post-to-threads) | Post to Threads using Ayrshare |
+| [Post To Tik Tok](block-integrations/ayrshare/post_to_tiktok.md#post-to-tik-tok) | Post to TikTok using Ayrshare |
+| [Post To X](block-integrations/ayrshare/post_to_x.md#post-to-x) | Post to X / Twitter using Ayrshare |
+| [Post To You Tube](block-integrations/ayrshare/post_to_youtube.md#post-to-you-tube) | Post to YouTube using Ayrshare |
+| [Publish To Medium](block-integrations/misc.md#publish-to-medium) | Publishes a post to Medium |
+| [Read Discord Messages](block-integrations/discord/bot_blocks.md#read-discord-messages) | Reads messages from a Discord channel using a bot token |
+| [Reddit Get My Posts](block-integrations/misc.md#reddit-get-my-posts) | Fetch posts created by the authenticated Reddit user (you) |
+| [Reply To Discord Message](block-integrations/discord/bot_blocks.md#reply-to-discord-message) | Replies to a specific Discord message |
+| [Reply To Reddit Comment](block-integrations/misc.md#reply-to-reddit-comment) | Reply to a specific Reddit comment |
+| [Search Reddit](block-integrations/misc.md#search-reddit) | Search Reddit for posts matching a query |
+| [Send Discord DM](block-integrations/discord/bot_blocks.md#send-discord-dm) | Sends a direct message to a Discord user using their user ID |
+| [Send Discord Embed](block-integrations/discord/bot_blocks.md#send-discord-embed) | Sends a rich embed message to a Discord channel |
+| [Send Discord File](block-integrations/discord/bot_blocks.md#send-discord-file) | Sends a file attachment to a Discord channel |
+| [Send Discord Message](block-integrations/discord/bot_blocks.md#send-discord-message) | Sends a message to a Discord channel using a bot token |
+| [Send Reddit Message](block-integrations/misc.md#send-reddit-message) | Send a private message (DM) to a Reddit user |
+| [Transcribe Youtube Video](block-integrations/misc.md#transcribe-youtube-video) | Transcribes a YouTube video using a proxy |
+| [Twitter Add List Member](block-integrations/twitter/list_members.md#twitter-add-list-member) | This block adds a specified user to a Twitter List owned by the authenticated user |
+| [Twitter Bookmark Tweet](block-integrations/twitter/bookmark.md#twitter-bookmark-tweet) | This block bookmarks a tweet on Twitter |
+| [Twitter Create List](block-integrations/twitter/manage_lists.md#twitter-create-list) | This block creates a new Twitter List for the authenticated user |
+| [Twitter Delete List](block-integrations/twitter/manage_lists.md#twitter-delete-list) | This block deletes a specified Twitter List owned by the authenticated user |
+| [Twitter Delete Tweet](block-integrations/twitter/manage.md#twitter-delete-tweet) | This block deletes a tweet on Twitter |
+| [Twitter Follow List](block-integrations/twitter/list_follows.md#twitter-follow-list) | This block follows a specified Twitter list for the authenticated user |
+| [Twitter Follow User](block-integrations/twitter/follows.md#twitter-follow-user) | This block follows a specified Twitter user |
+| [Twitter Get Blocked Users](block-integrations/twitter/blocks.md#twitter-get-blocked-users) | This block retrieves a list of users blocked by the authenticating user |
+| [Twitter Get Bookmarked Tweets](block-integrations/twitter/bookmark.md#twitter-get-bookmarked-tweets) | This block retrieves bookmarked tweets from Twitter |
+| [Twitter Get Followers](block-integrations/twitter/follows.md#twitter-get-followers) | This block retrieves followers of a specified Twitter user |
+| [Twitter Get Following](block-integrations/twitter/follows.md#twitter-get-following) | This block retrieves the users that a specified Twitter user is following |
+| [Twitter Get Home Timeline](block-integrations/twitter/timeline.md#twitter-get-home-timeline) | This block retrieves the authenticated user's home timeline |
+| [Twitter Get Liked Tweets](block-integrations/twitter/like.md#twitter-get-liked-tweets) | This block gets information about tweets liked by a user |
+| [Twitter Get Liking Users](block-integrations/twitter/like.md#twitter-get-liking-users) | This block gets information about users who liked a tweet |
+| [Twitter Get List](block-integrations/twitter/list_lookup.md#twitter-get-list) | This block retrieves information about a specified Twitter List |
+| [Twitter Get List Members](block-integrations/twitter/list_members.md#twitter-get-list-members) | This block retrieves the members of a specified Twitter List |
+| [Twitter Get List Memberships](block-integrations/twitter/list_members.md#twitter-get-list-memberships) | This block retrieves all Lists that a specified user is a member of |
+| [Twitter Get List Tweets](block-integrations/twitter/list_tweets_lookup.md#twitter-get-list-tweets) | This block retrieves tweets from a specified Twitter list |
+| [Twitter Get Muted Users](block-integrations/twitter/mutes.md#twitter-get-muted-users) | This block gets a list of users muted by the authenticating user |
+| [Twitter Get Owned Lists](block-integrations/twitter/list_lookup.md#twitter-get-owned-lists) | This block retrieves all Lists owned by a specified Twitter user |
+| [Twitter Get Pinned Lists](block-integrations/twitter/pinned_lists.md#twitter-get-pinned-lists) | This block returns the Lists pinned by the authenticated user |
+| [Twitter Get Quote Tweets](block-integrations/twitter/quote.md#twitter-get-quote-tweets) | This block gets quote tweets for a specific tweet |
+| [Twitter Get Retweeters](block-integrations/twitter/retweet.md#twitter-get-retweeters) | This block gets information about who has retweeted a tweet |
+| [Twitter Get Space Buyers](block-integrations/twitter/spaces_lookup.md#twitter-get-space-buyers) | This block retrieves a list of users who purchased tickets to a Twitter Space |
+| [Twitter Get Space By Id](block-integrations/twitter/spaces_lookup.md#twitter-get-space-by-id) | This block retrieves information about a single Twitter Space |
+| [Twitter Get Space Tweets](block-integrations/twitter/spaces_lookup.md#twitter-get-space-tweets) | This block retrieves tweets shared in a Twitter Space |
+| [Twitter Get Spaces](block-integrations/twitter/spaces_lookup.md#twitter-get-spaces) | This block retrieves information about multiple Twitter Spaces |
+| [Twitter Get Tweet](block-integrations/twitter/tweet_lookup.md#twitter-get-tweet) | This block retrieves information about a specific Tweet |
+| [Twitter Get Tweets](block-integrations/twitter/tweet_lookup.md#twitter-get-tweets) | This block retrieves information about multiple Tweets |
+| [Twitter Get User](block-integrations/twitter/user_lookup.md#twitter-get-user) | This block retrieves information about a specified Twitter user |
+| [Twitter Get User Mentions](block-integrations/twitter/timeline.md#twitter-get-user-mentions) | This block retrieves Tweets mentioning a specific user |
+| [Twitter Get User Tweets](block-integrations/twitter/timeline.md#twitter-get-user-tweets) | This block retrieves Tweets composed by a single user |
+| [Twitter Get Users](block-integrations/twitter/user_lookup.md#twitter-get-users) | This block retrieves information about multiple Twitter users |
+| [Twitter Hide Reply](block-integrations/twitter/hide.md#twitter-hide-reply) | This block hides a reply to a tweet |
+| [Twitter Like Tweet](block-integrations/twitter/like.md#twitter-like-tweet) | This block likes a tweet |
+| [Twitter Mute User](block-integrations/twitter/mutes.md#twitter-mute-user) | This block mutes a specified Twitter user |
+| [Twitter Pin List](block-integrations/twitter/pinned_lists.md#twitter-pin-list) | This block allows the authenticated user to pin a specified List |
+| [Twitter Post Tweet](block-integrations/twitter/manage.md#twitter-post-tweet) | This block posts a tweet on Twitter |
+| [Twitter Remove Bookmark Tweet](block-integrations/twitter/bookmark.md#twitter-remove-bookmark-tweet) | This block removes a bookmark from a tweet on Twitter |
+| [Twitter Remove List Member](block-integrations/twitter/list_members.md#twitter-remove-list-member) | This block removes a specified user from a Twitter List owned by the authenticated user |
+| [Twitter Remove Retweet](block-integrations/twitter/retweet.md#twitter-remove-retweet) | This block removes a retweet on Twitter |
+| [Twitter Retweet](block-integrations/twitter/retweet.md#twitter-retweet) | This block retweets a tweet on Twitter |
+| [Twitter Search Recent Tweets](block-integrations/twitter/manage.md#twitter-search-recent-tweets) | This block searches all public Tweets in Twitter history |
+| [Twitter Search Spaces](block-integrations/twitter/search_spaces.md#twitter-search-spaces) | This block searches for Twitter Spaces based on specified terms |
+| [Twitter Unfollow List](block-integrations/twitter/list_follows.md#twitter-unfollow-list) | This block unfollows a specified Twitter list for the authenticated user |
+| [Twitter Unfollow User](block-integrations/twitter/follows.md#twitter-unfollow-user) | This block unfollows a specified Twitter user |
+| [Twitter Unhide Reply](block-integrations/twitter/hide.md#twitter-unhide-reply) | This block unhides a reply to a tweet |
+| [Twitter Unlike Tweet](block-integrations/twitter/like.md#twitter-unlike-tweet) | This block unlikes a tweet |
+| [Twitter Unmute User](block-integrations/twitter/mutes.md#twitter-unmute-user) | This block unmutes a specified Twitter user |
+| [Twitter Unpin List](block-integrations/twitter/pinned_lists.md#twitter-unpin-list) | This block allows the authenticated user to unpin a specified List |
+| [Twitter Update List](block-integrations/twitter/manage_lists.md#twitter-update-list) | This block updates a specified Twitter List owned by the authenticated user |
## Communication
| Block Name | Description |
|------------|-------------|
-| [Baas Bot Join Meeting](baas/bots.md#baas-bot-join-meeting) | Deploy a bot to join and record a meeting |
-| [Baas Bot Leave Meeting](baas/bots.md#baas-bot-leave-meeting) | Remove a bot from an ongoing meeting |
-| [Gmail Add Label](google/gmail.md#gmail-add-label) | A block that adds a label to a specific email message in Gmail, creating the label if it doesn't exist |
-| [Gmail Create Draft](google/gmail.md#gmail-create-draft) | Create draft emails in Gmail with automatic HTML detection and proper text formatting |
-| [Gmail Draft Reply](google/gmail.md#gmail-draft-reply) | Create draft replies to Gmail threads with automatic HTML detection and proper text formatting |
-| [Gmail Forward](google/gmail.md#gmail-forward) | Forward Gmail messages to other recipients with automatic HTML detection and proper formatting |
-| [Gmail Get Profile](google/gmail.md#gmail-get-profile) | Get the authenticated user's Gmail profile details including email address and message statistics |
-| [Gmail Get Thread](google/gmail.md#gmail-get-thread) | A block that retrieves an entire Gmail thread (email conversation) by ID, returning all messages with decoded bodies for reading complete conversations |
-| [Gmail List Labels](google/gmail.md#gmail-list-labels) | A block that retrieves all labels (categories) from a Gmail account for organizing and categorizing emails |
-| [Gmail Read](google/gmail.md#gmail-read) | A block that retrieves and reads emails from a Gmail account based on search criteria, returning detailed message information including subject, sender, body, and attachments |
-| [Gmail Remove Label](google/gmail.md#gmail-remove-label) | A block that removes a label from a specific email message in a Gmail account |
-| [Gmail Reply](google/gmail.md#gmail-reply) | Reply to Gmail threads with automatic HTML detection and proper text formatting |
-| [Gmail Send](google/gmail.md#gmail-send) | Send emails via Gmail with automatic HTML detection and proper text formatting |
-| [Hub Spot Engagement](hubspot/engagement.md#hub-spot-engagement) | Manages HubSpot engagements - sends emails and tracks engagement metrics |
+| [Baas Bot Join Meeting](block-integrations/baas/bots.md#baas-bot-join-meeting) | Deploy a bot to join and record a meeting |
+| [Baas Bot Leave Meeting](block-integrations/baas/bots.md#baas-bot-leave-meeting) | Remove a bot from an ongoing meeting |
+| [Gmail Add Label](block-integrations/google/gmail.md#gmail-add-label) | A block that adds a label to a specific email message in Gmail, creating the label if it doesn't exist |
+| [Gmail Create Draft](block-integrations/google/gmail.md#gmail-create-draft) | Create draft emails in Gmail with automatic HTML detection and proper text formatting |
+| [Gmail Draft Reply](block-integrations/google/gmail.md#gmail-draft-reply) | Create draft replies to Gmail threads with automatic HTML detection and proper text formatting |
+| [Gmail Forward](block-integrations/google/gmail.md#gmail-forward) | Forward Gmail messages to other recipients with automatic HTML detection and proper formatting |
+| [Gmail Get Profile](block-integrations/google/gmail.md#gmail-get-profile) | Get the authenticated user's Gmail profile details including email address and message statistics |
+| [Gmail Get Thread](block-integrations/google/gmail.md#gmail-get-thread) | A block that retrieves an entire Gmail thread (email conversation) by ID, returning all messages with decoded bodies for reading complete conversations |
+| [Gmail List Labels](block-integrations/google/gmail.md#gmail-list-labels) | A block that retrieves all labels (categories) from a Gmail account for organizing and categorizing emails |
+| [Gmail Read](block-integrations/google/gmail.md#gmail-read) | A block that retrieves and reads emails from a Gmail account based on search criteria, returning detailed message information including subject, sender, body, and attachments |
+| [Gmail Remove Label](block-integrations/google/gmail.md#gmail-remove-label) | A block that removes a label from a specific email message in a Gmail account |
+| [Gmail Reply](block-integrations/google/gmail.md#gmail-reply) | Reply to Gmail threads with automatic HTML detection and proper text formatting |
+| [Gmail Send](block-integrations/google/gmail.md#gmail-send) | Send emails via Gmail with automatic HTML detection and proper text formatting |
+| [Hub Spot Engagement](block-integrations/hubspot/engagement.md#hub-spot-engagement) | Manages HubSpot engagements - sends emails and tracks engagement metrics |
## Developer Tools
| Block Name | Description |
|------------|-------------|
-| [Exa Code Context](exa/code_context.md#exa-code-context) | Search billions of GitHub repos, docs, and Stack Overflow for relevant code examples |
-| [Execute Code](misc.md#execute-code) | Executes code in a sandbox environment with internet access |
-| [Execute Code Step](misc.md#execute-code-step) | Execute code in a previously instantiated sandbox |
-| [Github Add Label](github/issues.md#github-add-label) | A block that adds a label to a GitHub issue or pull request for categorization and organization |
-| [Github Assign Issue](github/issues.md#github-assign-issue) | A block that assigns a GitHub user to an issue for task ownership and tracking |
-| [Github Assign PR Reviewer](github/pull_requests.md#github-assign-pr-reviewer) | This block assigns a reviewer to a specified GitHub pull request |
-| [Github Comment](github/issues.md#github-comment) | A block that posts comments on GitHub issues or pull requests using the GitHub API |
-| [Github Create Check Run](github/checks.md#github-create-check-run) | Creates a new check run for a specific commit in a GitHub repository |
-| [Github Create Comment Object](github/reviews.md#github-create-comment-object) | Creates a comment object for use with GitHub blocks |
-| [Github Create File](github/repo.md#github-create-file) | This block creates a new file in a GitHub repository |
-| [Github Create PR Review](github/reviews.md#github-create-pr-review) | This block creates a review on a GitHub pull request with optional inline comments |
-| [Github Create Repository](github/repo.md#github-create-repository) | This block creates a new GitHub repository |
-| [Github Create Status](github/statuses.md#github-create-status) | Creates a new commit status in a GitHub repository |
-| [Github Delete Branch](github/repo.md#github-delete-branch) | This block deletes a specified branch |
-| [Github Discussion Trigger](github/triggers.md#github-discussion-trigger) | This block triggers on GitHub Discussions events |
-| [Github Get CI Results](github/ci.md#github-get-ci-results) | This block gets CI results for a commit or PR, with optional search for specific errors/warnings in logs |
-| [Github Get PR Review Comments](github/reviews.md#github-get-pr-review-comments) | This block gets all review comments from a GitHub pull request or from a specific review |
-| [Github Issues Trigger](github/triggers.md#github-issues-trigger) | This block triggers on GitHub issues events |
-| [Github List Branches](github/repo.md#github-list-branches) | This block lists all branches for a specified GitHub repository |
-| [Github List Comments](github/issues.md#github-list-comments) | A block that retrieves all comments from a GitHub issue or pull request, including comment metadata and content |
-| [Github List Discussions](github/repo.md#github-list-discussions) | This block lists recent discussions for a specified GitHub repository |
-| [Github List Issues](github/issues.md#github-list-issues) | A block that retrieves a list of issues from a GitHub repository with their titles and URLs |
-| [Github List PR Reviewers](github/pull_requests.md#github-list-pr-reviewers) | This block lists all reviewers for a specified GitHub pull request |
-| [Github List PR Reviews](github/reviews.md#github-list-pr-reviews) | This block lists all reviews for a specified GitHub pull request |
-| [Github List Pull Requests](github/pull_requests.md#github-list-pull-requests) | This block lists all pull requests for a specified GitHub repository |
-| [Github List Releases](github/repo.md#github-list-releases) | This block lists all releases for a specified GitHub repository |
-| [Github List Stargazers](github/repo.md#github-list-stargazers) | This block lists all users who have starred a specified GitHub repository |
-| [Github List Tags](github/repo.md#github-list-tags) | This block lists all tags for a specified GitHub repository |
-| [Github Make Branch](github/repo.md#github-make-branch) | This block creates a new branch from a specified source branch |
-| [Github Make Issue](github/issues.md#github-make-issue) | A block that creates new issues on GitHub repositories with a title and body content |
-| [Github Make Pull Request](github/pull_requests.md#github-make-pull-request) | This block creates a new pull request on a specified GitHub repository |
-| [Github Pull Request Trigger](github/triggers.md#github-pull-request-trigger) | This block triggers on pull request events and outputs the event type and payload |
-| [Github Read File](github/repo.md#github-read-file) | This block reads the content of a specified file from a GitHub repository |
-| [Github Read Folder](github/repo.md#github-read-folder) | This block reads the content of a specified folder from a GitHub repository |
-| [Github Read Issue](github/issues.md#github-read-issue) | A block that retrieves information about a specific GitHub issue, including its title, body content, and creator |
-| [Github Read Pull Request](github/pull_requests.md#github-read-pull-request) | This block reads the body, title, user, and changes of a specified GitHub pull request |
-| [Github Release Trigger](github/triggers.md#github-release-trigger) | This block triggers on GitHub release events |
-| [Github Remove Label](github/issues.md#github-remove-label) | A block that removes a label from a GitHub issue or pull request |
-| [Github Resolve Review Discussion](github/reviews.md#github-resolve-review-discussion) | This block resolves or unresolves a review discussion thread on a GitHub pull request |
-| [Github Star Trigger](github/triggers.md#github-star-trigger) | This block triggers on GitHub star events |
-| [Github Submit Pending Review](github/reviews.md#github-submit-pending-review) | This block submits a pending (draft) review on a GitHub pull request |
-| [Github Unassign Issue](github/issues.md#github-unassign-issue) | A block that removes a user's assignment from a GitHub issue |
-| [Github Unassign PR Reviewer](github/pull_requests.md#github-unassign-pr-reviewer) | This block unassigns a reviewer from a specified GitHub pull request |
-| [Github Update Check Run](github/checks.md#github-update-check-run) | Updates an existing check run in a GitHub repository |
-| [Github Update Comment](github/issues.md#github-update-comment) | A block that updates an existing comment on a GitHub issue or pull request |
-| [Github Update File](github/repo.md#github-update-file) | This block updates an existing file in a GitHub repository |
-| [Instantiate Code Sandbox](misc.md#instantiate-code-sandbox) | Instantiate a sandbox environment with internet access in which you can execute code with the Execute Code Step block |
-| [Slant3D Order Webhook](slant3d/webhook.md#slant3d-order-webhook) | This block triggers on Slant3D order status updates and outputs the event details, including tracking information when orders are shipped |
+| [Exa Code Context](block-integrations/exa/code_context.md#exa-code-context) | Search billions of GitHub repos, docs, and Stack Overflow for relevant code examples |
+| [Execute Code](block-integrations/misc.md#execute-code) | Executes code in a sandbox environment with internet access |
+| [Execute Code Step](block-integrations/misc.md#execute-code-step) | Execute code in a previously instantiated sandbox |
+| [Github Add Label](block-integrations/github/issues.md#github-add-label) | A block that adds a label to a GitHub issue or pull request for categorization and organization |
+| [Github Assign Issue](block-integrations/github/issues.md#github-assign-issue) | A block that assigns a GitHub user to an issue for task ownership and tracking |
+| [Github Assign PR Reviewer](block-integrations/github/pull_requests.md#github-assign-pr-reviewer) | This block assigns a reviewer to a specified GitHub pull request |
+| [Github Comment](block-integrations/github/issues.md#github-comment) | A block that posts comments on GitHub issues or pull requests using the GitHub API |
+| [Github Create Check Run](block-integrations/github/checks.md#github-create-check-run) | Creates a new check run for a specific commit in a GitHub repository |
+| [Github Create Comment Object](block-integrations/github/reviews.md#github-create-comment-object) | Creates a comment object for use with GitHub blocks |
+| [Github Create File](block-integrations/github/repo.md#github-create-file) | This block creates a new file in a GitHub repository |
+| [Github Create PR Review](block-integrations/github/reviews.md#github-create-pr-review) | This block creates a review on a GitHub pull request with optional inline comments |
+| [Github Create Repository](block-integrations/github/repo.md#github-create-repository) | This block creates a new GitHub repository |
+| [Github Create Status](block-integrations/github/statuses.md#github-create-status) | Creates a new commit status in a GitHub repository |
+| [Github Delete Branch](block-integrations/github/repo.md#github-delete-branch) | This block deletes a specified branch |
+| [Github Discussion Trigger](block-integrations/github/triggers.md#github-discussion-trigger) | This block triggers on GitHub Discussions events |
+| [Github Get CI Results](block-integrations/github/ci.md#github-get-ci-results) | This block gets CI results for a commit or PR, with optional search for specific errors/warnings in logs |
+| [Github Get PR Review Comments](block-integrations/github/reviews.md#github-get-pr-review-comments) | This block gets all review comments from a GitHub pull request or from a specific review |
+| [Github Issues Trigger](block-integrations/github/triggers.md#github-issues-trigger) | This block triggers on GitHub issues events |
+| [Github List Branches](block-integrations/github/repo.md#github-list-branches) | This block lists all branches for a specified GitHub repository |
+| [Github List Comments](block-integrations/github/issues.md#github-list-comments) | A block that retrieves all comments from a GitHub issue or pull request, including comment metadata and content |
+| [Github List Discussions](block-integrations/github/repo.md#github-list-discussions) | This block lists recent discussions for a specified GitHub repository |
+| [Github List Issues](block-integrations/github/issues.md#github-list-issues) | A block that retrieves a list of issues from a GitHub repository with their titles and URLs |
+| [Github List PR Reviewers](block-integrations/github/pull_requests.md#github-list-pr-reviewers) | This block lists all reviewers for a specified GitHub pull request |
+| [Github List PR Reviews](block-integrations/github/reviews.md#github-list-pr-reviews) | This block lists all reviews for a specified GitHub pull request |
+| [Github List Pull Requests](block-integrations/github/pull_requests.md#github-list-pull-requests) | This block lists all pull requests for a specified GitHub repository |
+| [Github List Releases](block-integrations/github/repo.md#github-list-releases) | This block lists all releases for a specified GitHub repository |
+| [Github List Stargazers](block-integrations/github/repo.md#github-list-stargazers) | This block lists all users who have starred a specified GitHub repository |
+| [Github List Tags](block-integrations/github/repo.md#github-list-tags) | This block lists all tags for a specified GitHub repository |
+| [Github Make Branch](block-integrations/github/repo.md#github-make-branch) | This block creates a new branch from a specified source branch |
+| [Github Make Issue](block-integrations/github/issues.md#github-make-issue) | A block that creates new issues on GitHub repositories with a title and body content |
+| [Github Make Pull Request](block-integrations/github/pull_requests.md#github-make-pull-request) | This block creates a new pull request on a specified GitHub repository |
+| [Github Pull Request Trigger](block-integrations/github/triggers.md#github-pull-request-trigger) | This block triggers on pull request events and outputs the event type and payload |
+| [Github Read File](block-integrations/github/repo.md#github-read-file) | This block reads the content of a specified file from a GitHub repository |
+| [Github Read Folder](block-integrations/github/repo.md#github-read-folder) | This block reads the content of a specified folder from a GitHub repository |
+| [Github Read Issue](block-integrations/github/issues.md#github-read-issue) | A block that retrieves information about a specific GitHub issue, including its title, body content, and creator |
+| [Github Read Pull Request](block-integrations/github/pull_requests.md#github-read-pull-request) | This block reads the body, title, user, and changes of a specified GitHub pull request |
+| [Github Release Trigger](block-integrations/github/triggers.md#github-release-trigger) | This block triggers on GitHub release events |
+| [Github Remove Label](block-integrations/github/issues.md#github-remove-label) | A block that removes a label from a GitHub issue or pull request |
+| [Github Resolve Review Discussion](block-integrations/github/reviews.md#github-resolve-review-discussion) | This block resolves or unresolves a review discussion thread on a GitHub pull request |
+| [Github Star Trigger](block-integrations/github/triggers.md#github-star-trigger) | This block triggers on GitHub star events |
+| [Github Submit Pending Review](block-integrations/github/reviews.md#github-submit-pending-review) | This block submits a pending (draft) review on a GitHub pull request |
+| [Github Unassign Issue](block-integrations/github/issues.md#github-unassign-issue) | A block that removes a user's assignment from a GitHub issue |
+| [Github Unassign PR Reviewer](block-integrations/github/pull_requests.md#github-unassign-pr-reviewer) | This block unassigns a reviewer from a specified GitHub pull request |
+| [Github Update Check Run](block-integrations/github/checks.md#github-update-check-run) | Updates an existing check run in a GitHub repository |
+| [Github Update Comment](block-integrations/github/issues.md#github-update-comment) | A block that updates an existing comment on a GitHub issue or pull request |
+| [Github Update File](block-integrations/github/repo.md#github-update-file) | This block updates an existing file in a GitHub repository |
+| [Instantiate Code Sandbox](block-integrations/misc.md#instantiate-code-sandbox) | Instantiate a sandbox environment with internet access in which you can execute code with the Execute Code Step block |
+| [Slant3D Order Webhook](block-integrations/slant3d/webhook.md#slant3d-order-webhook) | This block triggers on Slant3D order status updates and outputs the event details, including tracking information when orders are shipped |
## Media Generation
| Block Name | Description |
|------------|-------------|
-| [Add Audio To Video](multimedia.md#add-audio-to-video) | Block to attach an audio file to a video file using moviepy |
-| [Loop Video](multimedia.md#loop-video) | Block to loop a video to a given duration or number of repeats |
-| [Media Duration](multimedia.md#media-duration) | Block to get the duration of a media file |
+| [Add Audio To Video](block-integrations/multimedia.md#add-audio-to-video) | Block to attach an audio file to a video file using moviepy |
+| [Loop Video](block-integrations/multimedia.md#loop-video) | Block to loop a video to a given duration or number of repeats |
+| [Media Duration](block-integrations/multimedia.md#media-duration) | Block to get the duration of a media file |
## Productivity
| Block Name | Description |
|------------|-------------|
-| [Google Calendar Create Event](google/calendar.md#google-calendar-create-event) | This block creates a new event in Google Calendar with customizable parameters |
-| [Notion Create Page](notion/create_page.md#notion-create-page) | Create a new page in Notion |
-| [Notion Read Database](notion/read_database.md#notion-read-database) | Query a Notion database with optional filtering and sorting, returning structured entries |
-| [Notion Read Page](notion/read_page.md#notion-read-page) | Read a Notion page by its ID and return its raw JSON |
-| [Notion Read Page Markdown](notion/read_page_markdown.md#notion-read-page-markdown) | Read a Notion page and convert it to Markdown format with proper formatting for headings, lists, links, and rich text |
-| [Notion Search](notion/search.md#notion-search) | Search your Notion workspace for pages and databases by text query |
-| [Todoist Close Task](todoist/tasks.md#todoist-close-task) | Closes a task in Todoist |
-| [Todoist Create Comment](todoist/comments.md#todoist-create-comment) | Creates a new comment on a Todoist task or project |
-| [Todoist Create Label](todoist/labels.md#todoist-create-label) | Creates a new label in Todoist, It will not work if same name already exists |
-| [Todoist Create Project](todoist/projects.md#todoist-create-project) | Creates a new project in Todoist |
-| [Todoist Create Task](todoist/tasks.md#todoist-create-task) | Creates a new task in a Todoist project |
-| [Todoist Delete Comment](todoist/comments.md#todoist-delete-comment) | Deletes a Todoist comment |
-| [Todoist Delete Label](todoist/labels.md#todoist-delete-label) | Deletes a personal label in Todoist |
-| [Todoist Delete Project](todoist/projects.md#todoist-delete-project) | Deletes a Todoist project and all its contents |
-| [Todoist Delete Section](todoist/sections.md#todoist-delete-section) | Deletes a section and all its tasks from Todoist |
-| [Todoist Delete Task](todoist/tasks.md#todoist-delete-task) | Deletes a task in Todoist |
-| [Todoist Get Comment](todoist/comments.md#todoist-get-comment) | Get a single comment from Todoist |
-| [Todoist Get Comments](todoist/comments.md#todoist-get-comments) | Get all comments for a Todoist task or project |
-| [Todoist Get Label](todoist/labels.md#todoist-get-label) | Gets a personal label from Todoist by ID |
-| [Todoist Get Project](todoist/projects.md#todoist-get-project) | Gets details for a specific Todoist project |
-| [Todoist Get Section](todoist/sections.md#todoist-get-section) | Gets a single section by ID from Todoist |
-| [Todoist Get Shared Labels](todoist/labels.md#todoist-get-shared-labels) | Gets all shared labels from Todoist |
-| [Todoist Get Task](todoist/tasks.md#todoist-get-task) | Get an active task from Todoist |
-| [Todoist Get Tasks](todoist/tasks.md#todoist-get-tasks) | Get active tasks from Todoist |
-| [Todoist List Collaborators](todoist/projects.md#todoist-list-collaborators) | Gets all collaborators for a specific Todoist project |
-| [Todoist List Labels](todoist/labels.md#todoist-list-labels) | Gets all personal labels from Todoist |
-| [Todoist List Projects](todoist/projects.md#todoist-list-projects) | Gets all projects and their details from Todoist |
-| [Todoist List Sections](todoist/sections.md#todoist-list-sections) | Gets all sections and their details from Todoist |
-| [Todoist Remove Shared Labels](todoist/labels.md#todoist-remove-shared-labels) | Removes all instances of a shared label |
-| [Todoist Rename Shared Labels](todoist/labels.md#todoist-rename-shared-labels) | Renames all instances of a shared label |
-| [Todoist Reopen Task](todoist/tasks.md#todoist-reopen-task) | Reopens a task in Todoist |
-| [Todoist Update Comment](todoist/comments.md#todoist-update-comment) | Updates a Todoist comment |
-| [Todoist Update Label](todoist/labels.md#todoist-update-label) | Updates a personal label in Todoist |
-| [Todoist Update Project](todoist/projects.md#todoist-update-project) | Updates an existing project in Todoist |
-| [Todoist Update Task](todoist/tasks.md#todoist-update-task) | Updates an existing task in Todoist |
+| [Google Calendar Create Event](block-integrations/google/calendar.md#google-calendar-create-event) | This block creates a new event in Google Calendar with customizable parameters |
+| [Notion Create Page](block-integrations/notion/create_page.md#notion-create-page) | Create a new page in Notion |
+| [Notion Read Database](block-integrations/notion/read_database.md#notion-read-database) | Query a Notion database with optional filtering and sorting, returning structured entries |
+| [Notion Read Page](block-integrations/notion/read_page.md#notion-read-page) | Read a Notion page by its ID and return its raw JSON |
+| [Notion Read Page Markdown](block-integrations/notion/read_page_markdown.md#notion-read-page-markdown) | Read a Notion page and convert it to Markdown format with proper formatting for headings, lists, links, and rich text |
+| [Notion Search](block-integrations/notion/search.md#notion-search) | Search your Notion workspace for pages and databases by text query |
+| [Todoist Close Task](block-integrations/todoist/tasks.md#todoist-close-task) | Closes a task in Todoist |
+| [Todoist Create Comment](block-integrations/todoist/comments.md#todoist-create-comment) | Creates a new comment on a Todoist task or project |
+| [Todoist Create Label](block-integrations/todoist/labels.md#todoist-create-label) | Creates a new label in Todoist, It will not work if same name already exists |
+| [Todoist Create Project](block-integrations/todoist/projects.md#todoist-create-project) | Creates a new project in Todoist |
+| [Todoist Create Task](block-integrations/todoist/tasks.md#todoist-create-task) | Creates a new task in a Todoist project |
+| [Todoist Delete Comment](block-integrations/todoist/comments.md#todoist-delete-comment) | Deletes a Todoist comment |
+| [Todoist Delete Label](block-integrations/todoist/labels.md#todoist-delete-label) | Deletes a personal label in Todoist |
+| [Todoist Delete Project](block-integrations/todoist/projects.md#todoist-delete-project) | Deletes a Todoist project and all its contents |
+| [Todoist Delete Section](block-integrations/todoist/sections.md#todoist-delete-section) | Deletes a section and all its tasks from Todoist |
+| [Todoist Delete Task](block-integrations/todoist/tasks.md#todoist-delete-task) | Deletes a task in Todoist |
+| [Todoist Get Comment](block-integrations/todoist/comments.md#todoist-get-comment) | Get a single comment from Todoist |
+| [Todoist Get Comments](block-integrations/todoist/comments.md#todoist-get-comments) | Get all comments for a Todoist task or project |
+| [Todoist Get Label](block-integrations/todoist/labels.md#todoist-get-label) | Gets a personal label from Todoist by ID |
+| [Todoist Get Project](block-integrations/todoist/projects.md#todoist-get-project) | Gets details for a specific Todoist project |
+| [Todoist Get Section](block-integrations/todoist/sections.md#todoist-get-section) | Gets a single section by ID from Todoist |
+| [Todoist Get Shared Labels](block-integrations/todoist/labels.md#todoist-get-shared-labels) | Gets all shared labels from Todoist |
+| [Todoist Get Task](block-integrations/todoist/tasks.md#todoist-get-task) | Get an active task from Todoist |
+| [Todoist Get Tasks](block-integrations/todoist/tasks.md#todoist-get-tasks) | Get active tasks from Todoist |
+| [Todoist List Collaborators](block-integrations/todoist/projects.md#todoist-list-collaborators) | Gets all collaborators for a specific Todoist project |
+| [Todoist List Labels](block-integrations/todoist/labels.md#todoist-list-labels) | Gets all personal labels from Todoist |
+| [Todoist List Projects](block-integrations/todoist/projects.md#todoist-list-projects) | Gets all projects and their details from Todoist |
+| [Todoist List Sections](block-integrations/todoist/sections.md#todoist-list-sections) | Gets all sections and their details from Todoist |
+| [Todoist Remove Shared Labels](block-integrations/todoist/labels.md#todoist-remove-shared-labels) | Removes all instances of a shared label |
+| [Todoist Rename Shared Labels](block-integrations/todoist/labels.md#todoist-rename-shared-labels) | Renames all instances of a shared label |
+| [Todoist Reopen Task](block-integrations/todoist/tasks.md#todoist-reopen-task) | Reopens a task in Todoist |
+| [Todoist Update Comment](block-integrations/todoist/comments.md#todoist-update-comment) | Updates a Todoist comment |
+| [Todoist Update Label](block-integrations/todoist/labels.md#todoist-update-label) | Updates a personal label in Todoist |
+| [Todoist Update Project](block-integrations/todoist/projects.md#todoist-update-project) | Updates an existing project in Todoist |
+| [Todoist Update Task](block-integrations/todoist/tasks.md#todoist-update-task) | Updates an existing task in Todoist |
## Logic and Control Flow
| Block Name | Description |
|------------|-------------|
-| [Calculator](logic.md#calculator) | Performs a mathematical operation on two numbers |
-| [Condition](logic.md#condition) | Handles conditional logic based on comparison operators |
-| [Count Items](logic.md#count-items) | Counts the number of items in a collection |
-| [Data Sampling](logic.md#data-sampling) | This block samples data from a given dataset using various sampling methods |
-| [Exa Webset Ready Check](exa/websets.md#exa-webset-ready-check) | Check if webset is ready for next operation - enables conditional workflow branching |
-| [If Input Matches](logic.md#if-input-matches) | Handles conditional logic based on comparison operators |
-| [Pinecone Init](logic.md#pinecone-init) | Initializes a Pinecone index |
-| [Pinecone Insert](logic.md#pinecone-insert) | Upload data to a Pinecone index |
-| [Pinecone Query](logic.md#pinecone-query) | Queries a Pinecone index |
-| [Step Through Items](logic.md#step-through-items) | Iterates over a list or dictionary and outputs each item |
+| [Calculator](block-integrations/logic.md#calculator) | Performs a mathematical operation on two numbers |
+| [Condition](block-integrations/logic.md#condition) | Handles conditional logic based on comparison operators |
+| [Count Items](block-integrations/logic.md#count-items) | Counts the number of items in a collection |
+| [Data Sampling](block-integrations/logic.md#data-sampling) | This block samples data from a given dataset using various sampling methods |
+| [Exa Webset Ready Check](block-integrations/exa/websets.md#exa-webset-ready-check) | Check if webset is ready for next operation - enables conditional workflow branching |
+| [If Input Matches](block-integrations/logic.md#if-input-matches) | Handles conditional logic based on comparison operators |
+| [Pinecone Init](block-integrations/logic.md#pinecone-init) | Initializes a Pinecone index |
+| [Pinecone Insert](block-integrations/logic.md#pinecone-insert) | Upload data to a Pinecone index |
+| [Pinecone Query](block-integrations/logic.md#pinecone-query) | Queries a Pinecone index |
+| [Step Through Items](block-integrations/logic.md#step-through-items) | Iterates over a list or dictionary and outputs each item |
## Input/Output
| Block Name | Description |
|------------|-------------|
-| [Exa Webset Webhook](exa/webhook_blocks.md#exa-webset-webhook) | Receive webhook notifications for Exa webset events |
-| [Generic Webhook Trigger](generic_webhook/triggers.md#generic-webhook-trigger) | This block will output the contents of the generic input for the webhook |
-| [Read RSS Feed](misc.md#read-rss-feed) | Reads RSS feed entries from a given URL |
-| [Send Authenticated Web Request](misc.md#send-authenticated-web-request) | Make an authenticated HTTP request with host-scoped credentials (JSON / form / multipart) |
-| [Send Email](misc.md#send-email) | This block sends an email using the provided SMTP credentials |
-| [Send Web Request](misc.md#send-web-request) | Make an HTTP request (JSON / form / multipart) |
+| [Exa Webset Webhook](block-integrations/exa/webhook_blocks.md#exa-webset-webhook) | Receive webhook notifications for Exa webset events |
+| [Generic Webhook Trigger](block-integrations/generic_webhook/triggers.md#generic-webhook-trigger) | This block will output the contents of the generic input for the webhook |
+| [Read RSS Feed](block-integrations/misc.md#read-rss-feed) | Reads RSS feed entries from a given URL |
+| [Send Authenticated Web Request](block-integrations/misc.md#send-authenticated-web-request) | Make an authenticated HTTP request with host-scoped credentials (JSON / form / multipart) |
+| [Send Email](block-integrations/misc.md#send-email) | This block sends an email using the provided SMTP credentials |
+| [Send Web Request](block-integrations/misc.md#send-web-request) | Make an HTTP request (JSON / form / multipart) |
## Agent Integration
| Block Name | Description |
|------------|-------------|
-| [Agent Executor](misc.md#agent-executor) | Executes an existing agent inside your agent |
+| [Agent Executor](block-integrations/misc.md#agent-executor) | Executes an existing agent inside your agent |
## CRM Services
| Block Name | Description |
|------------|-------------|
-| [Add Lead To Campaign](smartlead/campaign.md#add-lead-to-campaign) | Add a lead to a campaign in SmartLead |
-| [Create Campaign](smartlead/campaign.md#create-campaign) | Create a campaign in SmartLead |
-| [Hub Spot Company](hubspot/company.md#hub-spot-company) | Manages HubSpot companies - create, update, and retrieve company information |
-| [Hub Spot Contact](hubspot/contact.md#hub-spot-contact) | Manages HubSpot contacts - create, update, and retrieve contact information |
-| [Save Campaign Sequences](smartlead/campaign.md#save-campaign-sequences) | Save sequences within a campaign |
+| [Add Lead To Campaign](block-integrations/smartlead/campaign.md#add-lead-to-campaign) | Add a lead to a campaign in SmartLead |
+| [Create Campaign](block-integrations/smartlead/campaign.md#create-campaign) | Create a campaign in SmartLead |
+| [Hub Spot Company](block-integrations/hubspot/company.md#hub-spot-company) | Manages HubSpot companies - create, update, and retrieve company information |
+| [Hub Spot Contact](block-integrations/hubspot/contact.md#hub-spot-contact) | Manages HubSpot contacts - create, update, and retrieve contact information |
+| [Save Campaign Sequences](block-integrations/smartlead/campaign.md#save-campaign-sequences) | Save sequences within a campaign |
## AI Safety
| Block Name | Description |
|------------|-------------|
-| [Nvidia Deepfake Detect](nvidia/deepfake.md#nvidia-deepfake-detect) | Detects potential deepfakes in images using Nvidia's AI API |
+| [Nvidia Deepfake Detect](block-integrations/nvidia/deepfake.md#nvidia-deepfake-detect) | Detects potential deepfakes in images using Nvidia's AI API |
## Issue Tracking
| Block Name | Description |
|------------|-------------|
-| [Linear Create Comment](linear/comment.md#linear-create-comment) | Creates a new comment on a Linear issue |
-| [Linear Create Issue](linear/issues.md#linear-create-issue) | Creates a new issue on Linear |
-| [Linear Get Project Issues](linear/issues.md#linear-get-project-issues) | Gets issues from a Linear project filtered by status and assignee |
-| [Linear Search Projects](linear/projects.md#linear-search-projects) | Searches for projects on Linear |
+| [Linear Create Comment](block-integrations/linear/comment.md#linear-create-comment) | Creates a new comment on a Linear issue |
+| [Linear Create Issue](block-integrations/linear/issues.md#linear-create-issue) | Creates a new issue on Linear |
+| [Linear Get Project Issues](block-integrations/linear/issues.md#linear-get-project-issues) | Gets issues from a Linear project filtered by status and assignee |
+| [Linear Search Projects](block-integrations/linear/projects.md#linear-search-projects) | Searches for projects on Linear |
## Hardware
| Block Name | Description |
|------------|-------------|
-| [Compass AI Trigger](compass/triggers.md#compass-ai-trigger) | This block will output the contents of the compass transcription |
+| [Compass AI Trigger](block-integrations/compass/triggers.md#compass-ai-trigger) | This block will output the contents of the compass transcription |
diff --git a/docs/integrations/SUMMARY.md b/docs/integrations/SUMMARY.md
new file mode 100644
index 0000000000..9ce440ca45
--- /dev/null
+++ b/docs/integrations/SUMMARY.md
@@ -0,0 +1,133 @@
+# Table of contents
+
+* [AutoGPT Blocks Overview](README.md)
+
+## Guides
+
+* [LLM Providers](guides/llm-providers.md)
+* [Voice Providers](guides/voice-providers.md)
+
+## Block Integrations
+
+* [Airtable Bases](block-integrations/airtable/bases.md)
+* [Airtable Records](block-integrations/airtable/records.md)
+* [Airtable Schema](block-integrations/airtable/schema.md)
+* [Airtable Triggers](block-integrations/airtable/triggers.md)
+* [Apollo Organization](block-integrations/apollo/organization.md)
+* [Apollo People](block-integrations/apollo/people.md)
+* [Apollo Person](block-integrations/apollo/person.md)
+* [Ayrshare Post To Bluesky](block-integrations/ayrshare/post_to_bluesky.md)
+* [Ayrshare Post To Facebook](block-integrations/ayrshare/post_to_facebook.md)
+* [Ayrshare Post To GMB](block-integrations/ayrshare/post_to_gmb.md)
+* [Ayrshare Post To Instagram](block-integrations/ayrshare/post_to_instagram.md)
+* [Ayrshare Post To LinkedIn](block-integrations/ayrshare/post_to_linkedin.md)
+* [Ayrshare Post To Pinterest](block-integrations/ayrshare/post_to_pinterest.md)
+* [Ayrshare Post To Reddit](block-integrations/ayrshare/post_to_reddit.md)
+* [Ayrshare Post To Snapchat](block-integrations/ayrshare/post_to_snapchat.md)
+* [Ayrshare Post To Telegram](block-integrations/ayrshare/post_to_telegram.md)
+* [Ayrshare Post To Threads](block-integrations/ayrshare/post_to_threads.md)
+* [Ayrshare Post To TikTok](block-integrations/ayrshare/post_to_tiktok.md)
+* [Ayrshare Post To X](block-integrations/ayrshare/post_to_x.md)
+* [Ayrshare Post To YouTube](block-integrations/ayrshare/post_to_youtube.md)
+* [Baas Bots](block-integrations/baas/bots.md)
+* [Bannerbear Text Overlay](block-integrations/bannerbear/text_overlay.md)
+* [Basic](block-integrations/basic.md)
+* [Compass Triggers](block-integrations/compass/triggers.md)
+* [Data](block-integrations/data.md)
+* [Dataforseo Keyword Suggestions](block-integrations/dataforseo/keyword_suggestions.md)
+* [Dataforseo Related Keywords](block-integrations/dataforseo/related_keywords.md)
+* [Discord Bot Blocks](block-integrations/discord/bot_blocks.md)
+* [Discord OAuth Blocks](block-integrations/discord/oauth_blocks.md)
+* [Enrichlayer LinkedIn](block-integrations/enrichlayer/linkedin.md)
+* [Exa Answers](block-integrations/exa/answers.md)
+* [Exa Code Context](block-integrations/exa/code_context.md)
+* [Exa Contents](block-integrations/exa/contents.md)
+* [Exa Research](block-integrations/exa/research.md)
+* [Exa Search](block-integrations/exa/search.md)
+* [Exa Similar](block-integrations/exa/similar.md)
+* [Exa Webhook Blocks](block-integrations/exa/webhook_blocks.md)
+* [Exa Websets](block-integrations/exa/websets.md)
+* [Exa Websets Enrichment](block-integrations/exa/websets_enrichment.md)
+* [Exa Websets Import Export](block-integrations/exa/websets_import_export.md)
+* [Exa Websets Items](block-integrations/exa/websets_items.md)
+* [Exa Websets Monitor](block-integrations/exa/websets_monitor.md)
+* [Exa Websets Polling](block-integrations/exa/websets_polling.md)
+* [Exa Websets Search](block-integrations/exa/websets_search.md)
+* [Fal AI Video Generator](block-integrations/fal/ai_video_generator.md)
+* [Firecrawl Crawl](block-integrations/firecrawl/crawl.md)
+* [Firecrawl Extract](block-integrations/firecrawl/extract.md)
+* [Firecrawl Map](block-integrations/firecrawl/map.md)
+* [Firecrawl Scrape](block-integrations/firecrawl/scrape.md)
+* [Firecrawl Search](block-integrations/firecrawl/search.md)
+* [Generic Webhook Triggers](block-integrations/generic_webhook/triggers.md)
+* [GitHub Checks](block-integrations/github/checks.md)
+* [GitHub CI](block-integrations/github/ci.md)
+* [GitHub Issues](block-integrations/github/issues.md)
+* [GitHub Pull Requests](block-integrations/github/pull_requests.md)
+* [GitHub Repo](block-integrations/github/repo.md)
+* [GitHub Reviews](block-integrations/github/reviews.md)
+* [GitHub Statuses](block-integrations/github/statuses.md)
+* [GitHub Triggers](block-integrations/github/triggers.md)
+* [Google Calendar](block-integrations/google/calendar.md)
+* [Google Docs](block-integrations/google/docs.md)
+* [Google Gmail](block-integrations/google/gmail.md)
+* [Google Sheets](block-integrations/google/sheets.md)
+* [HubSpot Company](block-integrations/hubspot/company.md)
+* [HubSpot Contact](block-integrations/hubspot/contact.md)
+* [HubSpot Engagement](block-integrations/hubspot/engagement.md)
+* [Jina Chunking](block-integrations/jina/chunking.md)
+* [Jina Embeddings](block-integrations/jina/embeddings.md)
+* [Jina Fact Checker](block-integrations/jina/fact_checker.md)
+* [Jina Search](block-integrations/jina/search.md)
+* [Linear Comment](block-integrations/linear/comment.md)
+* [Linear Issues](block-integrations/linear/issues.md)
+* [Linear Projects](block-integrations/linear/projects.md)
+* [LLM](block-integrations/llm.md)
+* [Logic](block-integrations/logic.md)
+* [Misc](block-integrations/misc.md)
+* [Multimedia](block-integrations/multimedia.md)
+* [Notion Create Page](block-integrations/notion/create_page.md)
+* [Notion Read Database](block-integrations/notion/read_database.md)
+* [Notion Read Page](block-integrations/notion/read_page.md)
+* [Notion Read Page Markdown](block-integrations/notion/read_page_markdown.md)
+* [Notion Search](block-integrations/notion/search.md)
+* [Nvidia Deepfake](block-integrations/nvidia/deepfake.md)
+* [Replicate Flux Advanced](block-integrations/replicate/flux_advanced.md)
+* [Replicate Replicate Block](block-integrations/replicate/replicate_block.md)
+* [Search](block-integrations/search.md)
+* [Slant3D Filament](block-integrations/slant3d/filament.md)
+* [Slant3D Order](block-integrations/slant3d/order.md)
+* [Slant3D Slicing](block-integrations/slant3d/slicing.md)
+* [Slant3D Webhook](block-integrations/slant3d/webhook.md)
+* [Smartlead Campaign](block-integrations/smartlead/campaign.md)
+* [Stagehand Blocks](block-integrations/stagehand/blocks.md)
+* [System Library Operations](block-integrations/system/library_operations.md)
+* [System Store Operations](block-integrations/system/store_operations.md)
+* [Text](block-integrations/text.md)
+* [Todoist Comments](block-integrations/todoist/comments.md)
+* [Todoist Labels](block-integrations/todoist/labels.md)
+* [Todoist Projects](block-integrations/todoist/projects.md)
+* [Todoist Sections](block-integrations/todoist/sections.md)
+* [Todoist Tasks](block-integrations/todoist/tasks.md)
+* [Twitter Blocks](block-integrations/twitter/blocks.md)
+* [Twitter Bookmark](block-integrations/twitter/bookmark.md)
+* [Twitter Follows](block-integrations/twitter/follows.md)
+* [Twitter Hide](block-integrations/twitter/hide.md)
+* [Twitter Like](block-integrations/twitter/like.md)
+* [Twitter List Follows](block-integrations/twitter/list_follows.md)
+* [Twitter List Lookup](block-integrations/twitter/list_lookup.md)
+* [Twitter List Members](block-integrations/twitter/list_members.md)
+* [Twitter List Tweets Lookup](block-integrations/twitter/list_tweets_lookup.md)
+* [Twitter Manage](block-integrations/twitter/manage.md)
+* [Twitter Manage Lists](block-integrations/twitter/manage_lists.md)
+* [Twitter Mutes](block-integrations/twitter/mutes.md)
+* [Twitter Pinned Lists](block-integrations/twitter/pinned_lists.md)
+* [Twitter Quote](block-integrations/twitter/quote.md)
+* [Twitter Retweet](block-integrations/twitter/retweet.md)
+* [Twitter Search Spaces](block-integrations/twitter/search_spaces.md)
+* [Twitter Spaces Lookup](block-integrations/twitter/spaces_lookup.md)
+* [Twitter Timeline](block-integrations/twitter/timeline.md)
+* [Twitter Tweet Lookup](block-integrations/twitter/tweet_lookup.md)
+* [Twitter User Lookup](block-integrations/twitter/user_lookup.md)
+* [Wolfram LLM API](block-integrations/wolfram/llm_api.md)
+* [Zerobounce Validate Emails](block-integrations/zerobounce/validate_emails.md)
diff --git a/docs/integrations/ai_condition.md b/docs/integrations/block-integrations/ai_condition.md
similarity index 100%
rename from docs/integrations/ai_condition.md
rename to docs/integrations/block-integrations/ai_condition.md
diff --git a/docs/integrations/ai_shortform_video_block.md b/docs/integrations/block-integrations/ai_shortform_video_block.md
similarity index 100%
rename from docs/integrations/ai_shortform_video_block.md
rename to docs/integrations/block-integrations/ai_shortform_video_block.md
diff --git a/docs/integrations/airtable/bases.md b/docs/integrations/block-integrations/airtable/bases.md
similarity index 100%
rename from docs/integrations/airtable/bases.md
rename to docs/integrations/block-integrations/airtable/bases.md
diff --git a/docs/integrations/airtable/records.md b/docs/integrations/block-integrations/airtable/records.md
similarity index 100%
rename from docs/integrations/airtable/records.md
rename to docs/integrations/block-integrations/airtable/records.md
diff --git a/docs/integrations/airtable/schema.md b/docs/integrations/block-integrations/airtable/schema.md
similarity index 100%
rename from docs/integrations/airtable/schema.md
rename to docs/integrations/block-integrations/airtable/schema.md
diff --git a/docs/integrations/airtable/triggers.md b/docs/integrations/block-integrations/airtable/triggers.md
similarity index 100%
rename from docs/integrations/airtable/triggers.md
rename to docs/integrations/block-integrations/airtable/triggers.md
diff --git a/docs/integrations/apollo/organization.md b/docs/integrations/block-integrations/apollo/organization.md
similarity index 100%
rename from docs/integrations/apollo/organization.md
rename to docs/integrations/block-integrations/apollo/organization.md
diff --git a/docs/integrations/apollo/people.md b/docs/integrations/block-integrations/apollo/people.md
similarity index 100%
rename from docs/integrations/apollo/people.md
rename to docs/integrations/block-integrations/apollo/people.md
diff --git a/docs/integrations/apollo/person.md b/docs/integrations/block-integrations/apollo/person.md
similarity index 100%
rename from docs/integrations/apollo/person.md
rename to docs/integrations/block-integrations/apollo/person.md
diff --git a/docs/integrations/ayrshare/post_to_bluesky.md b/docs/integrations/block-integrations/ayrshare/post_to_bluesky.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_bluesky.md
rename to docs/integrations/block-integrations/ayrshare/post_to_bluesky.md
diff --git a/docs/integrations/ayrshare/post_to_facebook.md b/docs/integrations/block-integrations/ayrshare/post_to_facebook.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_facebook.md
rename to docs/integrations/block-integrations/ayrshare/post_to_facebook.md
diff --git a/docs/integrations/ayrshare/post_to_gmb.md b/docs/integrations/block-integrations/ayrshare/post_to_gmb.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_gmb.md
rename to docs/integrations/block-integrations/ayrshare/post_to_gmb.md
diff --git a/docs/integrations/ayrshare/post_to_instagram.md b/docs/integrations/block-integrations/ayrshare/post_to_instagram.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_instagram.md
rename to docs/integrations/block-integrations/ayrshare/post_to_instagram.md
diff --git a/docs/integrations/ayrshare/post_to_linkedin.md b/docs/integrations/block-integrations/ayrshare/post_to_linkedin.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_linkedin.md
rename to docs/integrations/block-integrations/ayrshare/post_to_linkedin.md
diff --git a/docs/integrations/ayrshare/post_to_pinterest.md b/docs/integrations/block-integrations/ayrshare/post_to_pinterest.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_pinterest.md
rename to docs/integrations/block-integrations/ayrshare/post_to_pinterest.md
diff --git a/docs/integrations/ayrshare/post_to_reddit.md b/docs/integrations/block-integrations/ayrshare/post_to_reddit.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_reddit.md
rename to docs/integrations/block-integrations/ayrshare/post_to_reddit.md
diff --git a/docs/integrations/ayrshare/post_to_snapchat.md b/docs/integrations/block-integrations/ayrshare/post_to_snapchat.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_snapchat.md
rename to docs/integrations/block-integrations/ayrshare/post_to_snapchat.md
diff --git a/docs/integrations/ayrshare/post_to_telegram.md b/docs/integrations/block-integrations/ayrshare/post_to_telegram.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_telegram.md
rename to docs/integrations/block-integrations/ayrshare/post_to_telegram.md
diff --git a/docs/integrations/ayrshare/post_to_threads.md b/docs/integrations/block-integrations/ayrshare/post_to_threads.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_threads.md
rename to docs/integrations/block-integrations/ayrshare/post_to_threads.md
diff --git a/docs/integrations/ayrshare/post_to_tiktok.md b/docs/integrations/block-integrations/ayrshare/post_to_tiktok.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_tiktok.md
rename to docs/integrations/block-integrations/ayrshare/post_to_tiktok.md
diff --git a/docs/integrations/ayrshare/post_to_x.md b/docs/integrations/block-integrations/ayrshare/post_to_x.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_x.md
rename to docs/integrations/block-integrations/ayrshare/post_to_x.md
diff --git a/docs/integrations/ayrshare/post_to_youtube.md b/docs/integrations/block-integrations/ayrshare/post_to_youtube.md
similarity index 100%
rename from docs/integrations/ayrshare/post_to_youtube.md
rename to docs/integrations/block-integrations/ayrshare/post_to_youtube.md
diff --git a/docs/integrations/baas/bots.md b/docs/integrations/block-integrations/baas/bots.md
similarity index 100%
rename from docs/integrations/baas/bots.md
rename to docs/integrations/block-integrations/baas/bots.md
diff --git a/docs/integrations/bannerbear/text_overlay.md b/docs/integrations/block-integrations/bannerbear/text_overlay.md
similarity index 100%
rename from docs/integrations/bannerbear/text_overlay.md
rename to docs/integrations/block-integrations/bannerbear/text_overlay.md
diff --git a/docs/integrations/basic.md b/docs/integrations/block-integrations/basic.md
similarity index 98%
rename from docs/integrations/basic.md
rename to docs/integrations/block-integrations/basic.md
index f92d19002f..5a73fd5a03 100644
--- a/docs/integrations/basic.md
+++ b/docs/integrations/block-integrations/basic.md
@@ -709,7 +709,7 @@ This is useful for conditional logic where you need to verify if data was return
## File Store
### What it is
-Stores the input file in the temporary directory.
+Downloads and stores a file from a URL, data URI, or local path. Use this to fetch images, documents, or other files for processing. In CoPilot: saves to workspace (use list_workspace_files to see it). In graphs: outputs a data URI to pass to other blocks.
### How it works
@@ -722,15 +722,15 @@ The block outputs a file path that other blocks can use to access the stored fil
| Input | Description | Type | Required |
|-------|-------------|------|----------|
-| file_in | The file to store in the temporary directory, it can be a URL, data URI, or local path. | str (file) | Yes |
-| base_64 | Whether produce an output in base64 format (not recommended, you can pass the string path just fine accross blocks). | bool | No |
+| file_in | The file to download and store. Can be a URL (https://...), data URI, or local path. | str (file) | Yes |
+| base_64 | Whether to produce output in base64 format (not recommended, you can pass the file reference across blocks). | bool | No |
### Outputs
| Output | Description | Type |
|--------|-------------|------|
| error | Error message if the operation failed | str |
-| file_out | The relative path to the stored file in the temporary directory. | str (file) |
+| file_out | Reference to the stored file. In CoPilot: workspace:// URI (visible in list_workspace_files). In graphs: data URI for passing to other blocks. | str (file) |
### Possible use case
diff --git a/docs/integrations/branching.md b/docs/integrations/block-integrations/branching.md
similarity index 100%
rename from docs/integrations/branching.md
rename to docs/integrations/block-integrations/branching.md
diff --git a/docs/integrations/block-integrations/claude_code.md b/docs/integrations/block-integrations/claude_code.md
new file mode 100644
index 0000000000..fea67cb494
--- /dev/null
+++ b/docs/integrations/block-integrations/claude_code.md
@@ -0,0 +1,67 @@
+# Claude Code Execution
+
+## What it is
+The Claude Code block executes complex coding tasks using Anthropic's Claude Code AI assistant in a secure E2B sandbox environment.
+
+## What it does
+This block allows you to delegate coding tasks to Claude Code, which can autonomously create files, install packages, run commands, and build complete applications within a sandboxed environment. Claude Code can handle multi-step development tasks and maintain conversation context across multiple turns.
+
+## How it works
+When activated, the block:
+1. Creates or connects to an E2B sandbox (a secure, isolated Linux environment)
+2. Installs the latest version of Claude Code in the sandbox
+3. Optionally runs setup commands to prepare the environment
+4. Executes your prompt using Claude Code, which can:
+ - Create and edit files
+ - Install dependencies (npm, pip, etc.)
+ - Run terminal commands
+ - Build and test applications
+5. Extracts all text files created/modified during execution
+6. Returns the response and files, optionally keeping the sandbox alive for follow-up tasks
+
+The block supports conversation continuation through three mechanisms:
+- **Same sandbox continuation** (via `session_id` + `sandbox_id`): Resume on the same live sandbox
+- **Fresh sandbox continuation** (via `conversation_history`): Restore context on a new sandbox if the previous one timed out
+- **Dispose control** (`dispose_sandbox` flag): Keep sandbox alive for multi-turn conversations
+
+## Inputs
+| Input | Description |
+|-------|-------------|
+| E2B Credentials | API key for the E2B platform to create the sandbox. Get one at [e2b.dev](https://e2b.dev/docs) |
+| Anthropic Credentials | API key for Anthropic to power Claude Code. Get one at [Anthropic's website](https://console.anthropic.com) |
+| Prompt | The task or instruction for Claude Code to execute. Claude Code can create files, install packages, run commands, and perform complex coding tasks |
+| Timeout | Sandbox timeout in seconds (default: 300). Set higher for complex tasks. Note: Only applies when creating a new sandbox |
+| Setup Commands | Optional shell commands to run before executing Claude Code (e.g., installing dependencies) |
+| Working Directory | Working directory for Claude Code to operate in (default: /home/user) |
+| Session ID | Session ID to resume a previous conversation. Leave empty for new conversations |
+| Sandbox ID | Sandbox ID to reconnect to an existing sandbox. Required when resuming a session |
+| Conversation History | Previous conversation history to restore context on a fresh sandbox if the previous one timed out |
+| Dispose Sandbox | Whether to dispose of the sandbox after execution (default: true). Set to false to continue conversations later |
+
+## Outputs
+| Output | Description |
+|--------|-------------|
+| Response | The output/response from Claude Code execution |
+| Files | List of text files created/modified during execution. Each file includes path, relative_path, name, and content fields |
+| Conversation History | Full conversation history including this turn. Use to restore context on a fresh sandbox |
+| Session ID | Session ID for this conversation. Pass back with sandbox_id to continue the conversation |
+| Sandbox ID | ID of the sandbox instance (null if disposed). Pass back with session_id to continue the conversation |
+| Error | Error message if execution failed |
+
+## Possible use case
+**API Documentation to Full Application:**
+A product team wants to quickly prototype applications based on API documentation. They create an agent that:
+1. Uses Firecrawl to fetch API documentation from a URL
+2. Passes the docs to Claude Code with a prompt like "Create a web app that demonstrates all the key features of this API"
+3. Claude Code builds a complete application with HTML/CSS/JS frontend, proper error handling, and example API calls
+4. The Files output is used with GitHub blocks to push the generated code to a new repository
+
+The team can then iterate on the application by passing the sandbox_id and session_id back to Claude Code with refinement requests like "Add authentication" or "Improve the UI", and Claude Code will modify the existing files in the same sandbox.
+
+**Multi-turn Development:**
+A developer uses Claude Code to scaffold a new project:
+- Turn 1: "Create a Python FastAPI project with user authentication" (dispose_sandbox=false)
+- Turn 2: Uses the returned session_id + sandbox_id to ask "Add rate limiting middleware"
+- Turn 3: Continues with "Add comprehensive tests"
+
+Each turn builds on the previous work in the same sandbox environment.
diff --git a/docs/integrations/compass/triggers.md b/docs/integrations/block-integrations/compass/triggers.md
similarity index 100%
rename from docs/integrations/compass/triggers.md
rename to docs/integrations/block-integrations/compass/triggers.md
diff --git a/docs/integrations/csv.md b/docs/integrations/block-integrations/csv.md
similarity index 100%
rename from docs/integrations/csv.md
rename to docs/integrations/block-integrations/csv.md
diff --git a/docs/integrations/data.md b/docs/integrations/block-integrations/data.md
similarity index 100%
rename from docs/integrations/data.md
rename to docs/integrations/block-integrations/data.md
diff --git a/docs/integrations/dataforseo/keyword_suggestions.md b/docs/integrations/block-integrations/dataforseo/keyword_suggestions.md
similarity index 100%
rename from docs/integrations/dataforseo/keyword_suggestions.md
rename to docs/integrations/block-integrations/dataforseo/keyword_suggestions.md
diff --git a/docs/integrations/dataforseo/related_keywords.md b/docs/integrations/block-integrations/dataforseo/related_keywords.md
similarity index 100%
rename from docs/integrations/dataforseo/related_keywords.md
rename to docs/integrations/block-integrations/dataforseo/related_keywords.md
diff --git a/docs/integrations/decoder_block.md b/docs/integrations/block-integrations/decoder_block.md
similarity index 100%
rename from docs/integrations/decoder_block.md
rename to docs/integrations/block-integrations/decoder_block.md
diff --git a/docs/integrations/discord.md b/docs/integrations/block-integrations/discord.md
similarity index 100%
rename from docs/integrations/discord.md
rename to docs/integrations/block-integrations/discord.md
diff --git a/docs/integrations/discord/bot_blocks.md b/docs/integrations/block-integrations/discord/bot_blocks.md
similarity index 100%
rename from docs/integrations/discord/bot_blocks.md
rename to docs/integrations/block-integrations/discord/bot_blocks.md
diff --git a/docs/integrations/discord/oauth_blocks.md b/docs/integrations/block-integrations/discord/oauth_blocks.md
similarity index 100%
rename from docs/integrations/discord/oauth_blocks.md
rename to docs/integrations/block-integrations/discord/oauth_blocks.md
diff --git a/docs/integrations/email_block.md b/docs/integrations/block-integrations/email_block.md
similarity index 100%
rename from docs/integrations/email_block.md
rename to docs/integrations/block-integrations/email_block.md
diff --git a/docs/integrations/enrichlayer/linkedin.md b/docs/integrations/block-integrations/enrichlayer/linkedin.md
similarity index 100%
rename from docs/integrations/enrichlayer/linkedin.md
rename to docs/integrations/block-integrations/enrichlayer/linkedin.md
diff --git a/docs/integrations/exa/answers.md b/docs/integrations/block-integrations/exa/answers.md
similarity index 100%
rename from docs/integrations/exa/answers.md
rename to docs/integrations/block-integrations/exa/answers.md
diff --git a/docs/integrations/exa/code_context.md b/docs/integrations/block-integrations/exa/code_context.md
similarity index 100%
rename from docs/integrations/exa/code_context.md
rename to docs/integrations/block-integrations/exa/code_context.md
diff --git a/docs/integrations/exa/contents.md b/docs/integrations/block-integrations/exa/contents.md
similarity index 100%
rename from docs/integrations/exa/contents.md
rename to docs/integrations/block-integrations/exa/contents.md
diff --git a/docs/integrations/exa/research.md b/docs/integrations/block-integrations/exa/research.md
similarity index 100%
rename from docs/integrations/exa/research.md
rename to docs/integrations/block-integrations/exa/research.md
diff --git a/docs/integrations/exa/search.md b/docs/integrations/block-integrations/exa/search.md
similarity index 100%
rename from docs/integrations/exa/search.md
rename to docs/integrations/block-integrations/exa/search.md
diff --git a/docs/integrations/exa/similar.md b/docs/integrations/block-integrations/exa/similar.md
similarity index 100%
rename from docs/integrations/exa/similar.md
rename to docs/integrations/block-integrations/exa/similar.md
diff --git a/docs/integrations/exa/webhook_blocks.md b/docs/integrations/block-integrations/exa/webhook_blocks.md
similarity index 100%
rename from docs/integrations/exa/webhook_blocks.md
rename to docs/integrations/block-integrations/exa/webhook_blocks.md
diff --git a/docs/integrations/exa/websets.md b/docs/integrations/block-integrations/exa/websets.md
similarity index 100%
rename from docs/integrations/exa/websets.md
rename to docs/integrations/block-integrations/exa/websets.md
diff --git a/docs/integrations/exa/websets_enrichment.md b/docs/integrations/block-integrations/exa/websets_enrichment.md
similarity index 100%
rename from docs/integrations/exa/websets_enrichment.md
rename to docs/integrations/block-integrations/exa/websets_enrichment.md
diff --git a/docs/integrations/exa/websets_import_export.md b/docs/integrations/block-integrations/exa/websets_import_export.md
similarity index 100%
rename from docs/integrations/exa/websets_import_export.md
rename to docs/integrations/block-integrations/exa/websets_import_export.md
diff --git a/docs/integrations/exa/websets_items.md b/docs/integrations/block-integrations/exa/websets_items.md
similarity index 100%
rename from docs/integrations/exa/websets_items.md
rename to docs/integrations/block-integrations/exa/websets_items.md
diff --git a/docs/integrations/exa/websets_monitor.md b/docs/integrations/block-integrations/exa/websets_monitor.md
similarity index 100%
rename from docs/integrations/exa/websets_monitor.md
rename to docs/integrations/block-integrations/exa/websets_monitor.md
diff --git a/docs/integrations/exa/websets_polling.md b/docs/integrations/block-integrations/exa/websets_polling.md
similarity index 100%
rename from docs/integrations/exa/websets_polling.md
rename to docs/integrations/block-integrations/exa/websets_polling.md
diff --git a/docs/integrations/exa/websets_search.md b/docs/integrations/block-integrations/exa/websets_search.md
similarity index 100%
rename from docs/integrations/exa/websets_search.md
rename to docs/integrations/block-integrations/exa/websets_search.md
diff --git a/docs/integrations/fal/ai_video_generator.md b/docs/integrations/block-integrations/fal/ai_video_generator.md
similarity index 100%
rename from docs/integrations/fal/ai_video_generator.md
rename to docs/integrations/block-integrations/fal/ai_video_generator.md
diff --git a/docs/integrations/firecrawl/crawl.md b/docs/integrations/block-integrations/firecrawl/crawl.md
similarity index 100%
rename from docs/integrations/firecrawl/crawl.md
rename to docs/integrations/block-integrations/firecrawl/crawl.md
diff --git a/docs/integrations/firecrawl/extract.md b/docs/integrations/block-integrations/firecrawl/extract.md
similarity index 100%
rename from docs/integrations/firecrawl/extract.md
rename to docs/integrations/block-integrations/firecrawl/extract.md
diff --git a/docs/integrations/firecrawl/map.md b/docs/integrations/block-integrations/firecrawl/map.md
similarity index 100%
rename from docs/integrations/firecrawl/map.md
rename to docs/integrations/block-integrations/firecrawl/map.md
diff --git a/docs/integrations/firecrawl/scrape.md b/docs/integrations/block-integrations/firecrawl/scrape.md
similarity index 100%
rename from docs/integrations/firecrawl/scrape.md
rename to docs/integrations/block-integrations/firecrawl/scrape.md
diff --git a/docs/integrations/firecrawl/search.md b/docs/integrations/block-integrations/firecrawl/search.md
similarity index 100%
rename from docs/integrations/firecrawl/search.md
rename to docs/integrations/block-integrations/firecrawl/search.md
diff --git a/docs/integrations/flux_kontext.md b/docs/integrations/block-integrations/flux_kontext.md
similarity index 100%
rename from docs/integrations/flux_kontext.md
rename to docs/integrations/block-integrations/flux_kontext.md
diff --git a/docs/integrations/generic_webhook/triggers.md b/docs/integrations/block-integrations/generic_webhook/triggers.md
similarity index 100%
rename from docs/integrations/generic_webhook/triggers.md
rename to docs/integrations/block-integrations/generic_webhook/triggers.md
diff --git a/docs/integrations/github/checks.md b/docs/integrations/block-integrations/github/checks.md
similarity index 100%
rename from docs/integrations/github/checks.md
rename to docs/integrations/block-integrations/github/checks.md
diff --git a/docs/integrations/github/ci.md b/docs/integrations/block-integrations/github/ci.md
similarity index 100%
rename from docs/integrations/github/ci.md
rename to docs/integrations/block-integrations/github/ci.md
diff --git a/docs/integrations/github/issues.md b/docs/integrations/block-integrations/github/issues.md
similarity index 100%
rename from docs/integrations/github/issues.md
rename to docs/integrations/block-integrations/github/issues.md
diff --git a/docs/integrations/github/pull_requests.md b/docs/integrations/block-integrations/github/pull_requests.md
similarity index 100%
rename from docs/integrations/github/pull_requests.md
rename to docs/integrations/block-integrations/github/pull_requests.md
diff --git a/docs/integrations/github/repo.md b/docs/integrations/block-integrations/github/repo.md
similarity index 100%
rename from docs/integrations/github/repo.md
rename to docs/integrations/block-integrations/github/repo.md
diff --git a/docs/integrations/github/reviews.md b/docs/integrations/block-integrations/github/reviews.md
similarity index 100%
rename from docs/integrations/github/reviews.md
rename to docs/integrations/block-integrations/github/reviews.md
diff --git a/docs/integrations/github/statuses.md b/docs/integrations/block-integrations/github/statuses.md
similarity index 100%
rename from docs/integrations/github/statuses.md
rename to docs/integrations/block-integrations/github/statuses.md
diff --git a/docs/integrations/github/triggers.md b/docs/integrations/block-integrations/github/triggers.md
similarity index 100%
rename from docs/integrations/github/triggers.md
rename to docs/integrations/block-integrations/github/triggers.md
diff --git a/docs/integrations/google/calendar.md b/docs/integrations/block-integrations/google/calendar.md
similarity index 100%
rename from docs/integrations/google/calendar.md
rename to docs/integrations/block-integrations/google/calendar.md
diff --git a/docs/integrations/google/docs.md b/docs/integrations/block-integrations/google/docs.md
similarity index 100%
rename from docs/integrations/google/docs.md
rename to docs/integrations/block-integrations/google/docs.md
diff --git a/docs/integrations/google/gmail.md b/docs/integrations/block-integrations/google/gmail.md
similarity index 100%
rename from docs/integrations/google/gmail.md
rename to docs/integrations/block-integrations/google/gmail.md
diff --git a/docs/integrations/google/sheet.md b/docs/integrations/block-integrations/google/sheet.md
similarity index 100%
rename from docs/integrations/google/sheet.md
rename to docs/integrations/block-integrations/google/sheet.md
diff --git a/docs/integrations/google/sheets.md b/docs/integrations/block-integrations/google/sheets.md
similarity index 100%
rename from docs/integrations/google/sheets.md
rename to docs/integrations/block-integrations/google/sheets.md
diff --git a/docs/integrations/google_maps.md b/docs/integrations/block-integrations/google_maps.md
similarity index 100%
rename from docs/integrations/google_maps.md
rename to docs/integrations/block-integrations/google_maps.md
diff --git a/docs/integrations/http.md b/docs/integrations/block-integrations/http.md
similarity index 100%
rename from docs/integrations/http.md
rename to docs/integrations/block-integrations/http.md
diff --git a/docs/integrations/hubspot/company.md b/docs/integrations/block-integrations/hubspot/company.md
similarity index 100%
rename from docs/integrations/hubspot/company.md
rename to docs/integrations/block-integrations/hubspot/company.md
diff --git a/docs/integrations/hubspot/contact.md b/docs/integrations/block-integrations/hubspot/contact.md
similarity index 100%
rename from docs/integrations/hubspot/contact.md
rename to docs/integrations/block-integrations/hubspot/contact.md
diff --git a/docs/integrations/hubspot/engagement.md b/docs/integrations/block-integrations/hubspot/engagement.md
similarity index 100%
rename from docs/integrations/hubspot/engagement.md
rename to docs/integrations/block-integrations/hubspot/engagement.md
diff --git a/docs/integrations/ideogram.md b/docs/integrations/block-integrations/ideogram.md
similarity index 100%
rename from docs/integrations/ideogram.md
rename to docs/integrations/block-integrations/ideogram.md
diff --git a/docs/integrations/iteration.md b/docs/integrations/block-integrations/iteration.md
similarity index 100%
rename from docs/integrations/iteration.md
rename to docs/integrations/block-integrations/iteration.md
diff --git a/docs/integrations/jina/chunking.md b/docs/integrations/block-integrations/jina/chunking.md
similarity index 100%
rename from docs/integrations/jina/chunking.md
rename to docs/integrations/block-integrations/jina/chunking.md
diff --git a/docs/integrations/jina/embeddings.md b/docs/integrations/block-integrations/jina/embeddings.md
similarity index 100%
rename from docs/integrations/jina/embeddings.md
rename to docs/integrations/block-integrations/jina/embeddings.md
diff --git a/docs/integrations/jina/fact_checker.md b/docs/integrations/block-integrations/jina/fact_checker.md
similarity index 100%
rename from docs/integrations/jina/fact_checker.md
rename to docs/integrations/block-integrations/jina/fact_checker.md
diff --git a/docs/integrations/jina/search.md b/docs/integrations/block-integrations/jina/search.md
similarity index 100%
rename from docs/integrations/jina/search.md
rename to docs/integrations/block-integrations/jina/search.md
diff --git a/docs/integrations/linear/comment.md b/docs/integrations/block-integrations/linear/comment.md
similarity index 100%
rename from docs/integrations/linear/comment.md
rename to docs/integrations/block-integrations/linear/comment.md
diff --git a/docs/integrations/linear/issues.md b/docs/integrations/block-integrations/linear/issues.md
similarity index 100%
rename from docs/integrations/linear/issues.md
rename to docs/integrations/block-integrations/linear/issues.md
diff --git a/docs/integrations/linear/projects.md b/docs/integrations/block-integrations/linear/projects.md
similarity index 100%
rename from docs/integrations/linear/projects.md
rename to docs/integrations/block-integrations/linear/projects.md
diff --git a/docs/integrations/llm.md b/docs/integrations/block-integrations/llm.md
similarity index 91%
rename from docs/integrations/llm.md
rename to docs/integrations/block-integrations/llm.md
index 4e75714e56..f4d69b912b 100644
--- a/docs/integrations/llm.md
+++ b/docs/integrations/block-integrations/llm.md
@@ -523,6 +523,62 @@ Summarizing lengthy research papers or articles to quickly grasp the main points
---
+## Claude Code
+
+### What it is
+Execute tasks using Claude Code in an E2B sandbox. Claude Code can create files, install tools, run commands, and perform complex coding tasks autonomously.
+
+### How it works
+
+When activated, the block:
+1. Creates or connects to an E2B sandbox (a secure, isolated Linux environment)
+2. Installs the latest version of Claude Code in the sandbox
+3. Optionally runs setup commands to prepare the environment
+4. Executes your prompt using Claude Code, which can create/edit files, install dependencies, run terminal commands, and build applications
+5. Extracts all text files created/modified during execution
+6. Returns the response and files, optionally keeping the sandbox alive for follow-up tasks
+
+The block supports conversation continuation through three mechanisms:
+- **Same sandbox continuation** (via `session_id` + `sandbox_id`): Resume on the same live sandbox
+- **Fresh sandbox continuation** (via `conversation_history`): Restore context on a new sandbox if the previous one timed out
+- **Dispose control** (`dispose_sandbox` flag): Keep sandbox alive for multi-turn conversations
+
+
+### Inputs
+
+| Input | Description | Type | Required |
+|-------|-------------|------|----------|
+| prompt | The task or instruction for Claude Code to execute. Claude Code can create files, install packages, run commands, and perform complex coding tasks. | str | No |
+| timeout | Sandbox timeout in seconds. Claude Code tasks can take a while, so set this appropriately for your task complexity. Note: This only applies when creating a new sandbox. When reconnecting to an existing sandbox via sandbox_id, the original timeout is retained. | int | No |
+| setup_commands | Optional shell commands to run before executing Claude Code. Useful for installing dependencies or setting up the environment. | List[str] | No |
+| working_directory | Working directory for Claude Code to operate in. | str | No |
+| session_id | Session ID to resume a previous conversation. Leave empty for a new conversation. Use the session_id from a previous run to continue that conversation. | str | No |
+| sandbox_id | Sandbox ID to reconnect to an existing sandbox. Required when resuming a session (along with session_id). Use the sandbox_id from a previous run where dispose_sandbox was False. | str | No |
+| conversation_history | Previous conversation history to continue from. Use this to restore context on a fresh sandbox if the previous one timed out. Pass the conversation_history output from a previous run. | str | No |
+| dispose_sandbox | Whether to dispose of the sandbox immediately after execution. Set to False if you want to continue the conversation later (you'll need both sandbox_id and session_id from the output). | bool | No |
+
+### Outputs
+
+| Output | Description | Type |
+|--------|-------------|------|
+| error | Error message if execution failed | str |
+| response | The output/response from Claude Code execution | str |
+| files | List of text files created/modified by Claude Code during this execution. Each file has 'path', 'relative_path', 'name', and 'content' fields. | List[FileOutput] |
+| conversation_history | Full conversation history including this turn. Pass this to conversation_history input to continue on a fresh sandbox if the previous sandbox timed out. | str |
+| session_id | Session ID for this conversation. Pass this back along with sandbox_id to continue the conversation. | str |
+| sandbox_id | ID of the sandbox instance. Pass this back along with session_id to continue the conversation. This is None if dispose_sandbox was True (sandbox was disposed). | str |
+
+### Possible use case
+
+**API Documentation to Full Application**: A product team wants to quickly prototype applications based on API documentation. They fetch API docs with Firecrawl, pass them to Claude Code with a prompt like "Create a web app that demonstrates all the key features of this API", and Claude Code builds a complete application with HTML/CSS/JS frontend, proper error handling, and example API calls. The Files output can then be pushed to GitHub.
+
+**Multi-turn Development**: A developer uses Claude Code to scaffold a new project iteratively - Turn 1: "Create a Python FastAPI project with user authentication" (dispose_sandbox=false), Turn 2: Uses the returned session_id + sandbox_id to ask "Add rate limiting middleware", Turn 3: Continues with "Add comprehensive tests". Each turn builds on the previous work in the same sandbox environment.
+
+**Automated Code Review and Fixes**: An agent receives code from a PR, sends it to Claude Code with "Review this code for bugs and security issues, then fix any problems you find", and Claude Code analyzes the code, makes fixes, and returns the corrected files ready to commit.
+
+
+---
+
## Code Generation
### What it is
diff --git a/docs/integrations/logic.md b/docs/integrations/block-integrations/logic.md
similarity index 100%
rename from docs/integrations/logic.md
rename to docs/integrations/block-integrations/logic.md
diff --git a/docs/integrations/maths.md b/docs/integrations/block-integrations/maths.md
similarity index 100%
rename from docs/integrations/maths.md
rename to docs/integrations/block-integrations/maths.md
diff --git a/docs/integrations/medium.md b/docs/integrations/block-integrations/medium.md
similarity index 100%
rename from docs/integrations/medium.md
rename to docs/integrations/block-integrations/medium.md
diff --git a/docs/integrations/misc.md b/docs/integrations/block-integrations/misc.md
similarity index 100%
rename from docs/integrations/misc.md
rename to docs/integrations/block-integrations/misc.md
diff --git a/docs/integrations/multimedia.md b/docs/integrations/block-integrations/multimedia.md
similarity index 89%
rename from docs/integrations/multimedia.md
rename to docs/integrations/block-integrations/multimedia.md
index e2d11cfbf7..6b8f261346 100644
--- a/docs/integrations/multimedia.md
+++ b/docs/integrations/block-integrations/multimedia.md
@@ -12,7 +12,7 @@ Block to attach an audio file to a video file using moviepy.
This block combines a video file with an audio file using the moviepy library. The audio track is attached to the video, optionally with volume adjustment via the volume parameter (1.0 = original volume).
-Input files can be URLs, data URIs, or local paths. The output can be returned as either a file path or base64 data URI.
+Input files can be URLs, data URIs, or local paths. The output format is automatically determined: `workspace://` URLs in CoPilot, data URIs in graph executions.
### Inputs
@@ -22,7 +22,6 @@ Input files can be URLs, data URIs, or local paths. The output can be returned a
| video_in | Video input (URL, data URI, or local path). | str (file) | Yes |
| audio_in | Audio input (URL, data URI, or local path). | str (file) | Yes |
| volume | Volume scale for the newly attached audio track (1.0 = original). | float | No |
-| output_return_type | Return the final output as a relative path or base64 data URI. | "file_path" \| "data_uri" | No |
### Outputs
@@ -51,7 +50,7 @@ Block to loop a video to a given duration or number of repeats.
This block extends a video by repeating it to reach a target duration or number of loops. Set duration to specify the total length in seconds, or use n_loops to repeat the video a specific number of times.
-The looped video is seamlessly concatenated and can be output as a file path or base64 data URI.
+The looped video is seamlessly concatenated. The output format is automatically determined: `workspace://` URLs in CoPilot, data URIs in graph executions.
### Inputs
@@ -61,7 +60,6 @@ The looped video is seamlessly concatenated and can be output as a file path or
| video_in | The input video (can be a URL, data URI, or local path). | str (file) | Yes |
| duration | Target duration (in seconds) to loop the video to. If omitted, defaults to no looping. | float | No |
| n_loops | Number of times to repeat the video. If omitted, defaults to 1 (no repeat). | int | No |
-| output_return_type | How to return the output video. Either a relative path or base64 data URI. | "file_path" \| "data_uri" | No |
### Outputs
diff --git a/docs/integrations/notion/create_page.md b/docs/integrations/block-integrations/notion/create_page.md
similarity index 100%
rename from docs/integrations/notion/create_page.md
rename to docs/integrations/block-integrations/notion/create_page.md
diff --git a/docs/integrations/notion/read_database.md b/docs/integrations/block-integrations/notion/read_database.md
similarity index 100%
rename from docs/integrations/notion/read_database.md
rename to docs/integrations/block-integrations/notion/read_database.md
diff --git a/docs/integrations/notion/read_page.md b/docs/integrations/block-integrations/notion/read_page.md
similarity index 100%
rename from docs/integrations/notion/read_page.md
rename to docs/integrations/block-integrations/notion/read_page.md
diff --git a/docs/integrations/notion/read_page_markdown.md b/docs/integrations/block-integrations/notion/read_page_markdown.md
similarity index 100%
rename from docs/integrations/notion/read_page_markdown.md
rename to docs/integrations/block-integrations/notion/read_page_markdown.md
diff --git a/docs/integrations/notion/search.md b/docs/integrations/block-integrations/notion/search.md
similarity index 100%
rename from docs/integrations/notion/search.md
rename to docs/integrations/block-integrations/notion/search.md
diff --git a/docs/integrations/nvidia/deepfake.md b/docs/integrations/block-integrations/nvidia/deepfake.md
similarity index 100%
rename from docs/integrations/nvidia/deepfake.md
rename to docs/integrations/block-integrations/nvidia/deepfake.md
diff --git a/docs/integrations/reddit.md b/docs/integrations/block-integrations/reddit.md
similarity index 100%
rename from docs/integrations/reddit.md
rename to docs/integrations/block-integrations/reddit.md
diff --git a/docs/integrations/replicate/flux_advanced.md b/docs/integrations/block-integrations/replicate/flux_advanced.md
similarity index 100%
rename from docs/integrations/replicate/flux_advanced.md
rename to docs/integrations/block-integrations/replicate/flux_advanced.md
diff --git a/docs/integrations/replicate/replicate_block.md b/docs/integrations/block-integrations/replicate/replicate_block.md
similarity index 100%
rename from docs/integrations/replicate/replicate_block.md
rename to docs/integrations/block-integrations/replicate/replicate_block.md
diff --git a/docs/integrations/replicate_flux_advanced.md b/docs/integrations/block-integrations/replicate_flux_advanced.md
similarity index 100%
rename from docs/integrations/replicate_flux_advanced.md
rename to docs/integrations/block-integrations/replicate_flux_advanced.md
diff --git a/docs/integrations/rss.md b/docs/integrations/block-integrations/rss.md
similarity index 100%
rename from docs/integrations/rss.md
rename to docs/integrations/block-integrations/rss.md
diff --git a/docs/integrations/sampling.md b/docs/integrations/block-integrations/sampling.md
similarity index 100%
rename from docs/integrations/sampling.md
rename to docs/integrations/block-integrations/sampling.md
diff --git a/docs/integrations/search.md b/docs/integrations/block-integrations/search.md
similarity index 100%
rename from docs/integrations/search.md
rename to docs/integrations/block-integrations/search.md
diff --git a/docs/integrations/slant3d/filament.md b/docs/integrations/block-integrations/slant3d/filament.md
similarity index 100%
rename from docs/integrations/slant3d/filament.md
rename to docs/integrations/block-integrations/slant3d/filament.md
diff --git a/docs/integrations/slant3d/order.md b/docs/integrations/block-integrations/slant3d/order.md
similarity index 100%
rename from docs/integrations/slant3d/order.md
rename to docs/integrations/block-integrations/slant3d/order.md
diff --git a/docs/integrations/slant3d/slicing.md b/docs/integrations/block-integrations/slant3d/slicing.md
similarity index 100%
rename from docs/integrations/slant3d/slicing.md
rename to docs/integrations/block-integrations/slant3d/slicing.md
diff --git a/docs/integrations/slant3d/webhook.md b/docs/integrations/block-integrations/slant3d/webhook.md
similarity index 100%
rename from docs/integrations/slant3d/webhook.md
rename to docs/integrations/block-integrations/slant3d/webhook.md
diff --git a/docs/integrations/smartlead/campaign.md b/docs/integrations/block-integrations/smartlead/campaign.md
similarity index 100%
rename from docs/integrations/smartlead/campaign.md
rename to docs/integrations/block-integrations/smartlead/campaign.md
diff --git a/docs/integrations/stagehand/blocks.md b/docs/integrations/block-integrations/stagehand/blocks.md
similarity index 100%
rename from docs/integrations/stagehand/blocks.md
rename to docs/integrations/block-integrations/stagehand/blocks.md
diff --git a/docs/integrations/system/library_operations.md b/docs/integrations/block-integrations/system/library_operations.md
similarity index 100%
rename from docs/integrations/system/library_operations.md
rename to docs/integrations/block-integrations/system/library_operations.md
diff --git a/docs/integrations/system/store_operations.md b/docs/integrations/block-integrations/system/store_operations.md
similarity index 100%
rename from docs/integrations/system/store_operations.md
rename to docs/integrations/block-integrations/system/store_operations.md
diff --git a/docs/integrations/talking_head.md b/docs/integrations/block-integrations/talking_head.md
similarity index 100%
rename from docs/integrations/talking_head.md
rename to docs/integrations/block-integrations/talking_head.md
diff --git a/docs/integrations/text.md b/docs/integrations/block-integrations/text.md
similarity index 100%
rename from docs/integrations/text.md
rename to docs/integrations/block-integrations/text.md
diff --git a/docs/integrations/text_to_speech_block.md b/docs/integrations/block-integrations/text_to_speech_block.md
similarity index 100%
rename from docs/integrations/text_to_speech_block.md
rename to docs/integrations/block-integrations/text_to_speech_block.md
diff --git a/docs/integrations/time_blocks.md b/docs/integrations/block-integrations/time_blocks.md
similarity index 100%
rename from docs/integrations/time_blocks.md
rename to docs/integrations/block-integrations/time_blocks.md
diff --git a/docs/integrations/todoist.md b/docs/integrations/block-integrations/todoist.md
similarity index 100%
rename from docs/integrations/todoist.md
rename to docs/integrations/block-integrations/todoist.md
diff --git a/docs/integrations/todoist/comments.md b/docs/integrations/block-integrations/todoist/comments.md
similarity index 100%
rename from docs/integrations/todoist/comments.md
rename to docs/integrations/block-integrations/todoist/comments.md
diff --git a/docs/integrations/todoist/labels.md b/docs/integrations/block-integrations/todoist/labels.md
similarity index 100%
rename from docs/integrations/todoist/labels.md
rename to docs/integrations/block-integrations/todoist/labels.md
diff --git a/docs/integrations/todoist/projects.md b/docs/integrations/block-integrations/todoist/projects.md
similarity index 100%
rename from docs/integrations/todoist/projects.md
rename to docs/integrations/block-integrations/todoist/projects.md
diff --git a/docs/integrations/todoist/sections.md b/docs/integrations/block-integrations/todoist/sections.md
similarity index 100%
rename from docs/integrations/todoist/sections.md
rename to docs/integrations/block-integrations/todoist/sections.md
diff --git a/docs/integrations/todoist/tasks.md b/docs/integrations/block-integrations/todoist/tasks.md
similarity index 100%
rename from docs/integrations/todoist/tasks.md
rename to docs/integrations/block-integrations/todoist/tasks.md
diff --git a/docs/integrations/twitter/blocks.md b/docs/integrations/block-integrations/twitter/blocks.md
similarity index 100%
rename from docs/integrations/twitter/blocks.md
rename to docs/integrations/block-integrations/twitter/blocks.md
diff --git a/docs/integrations/twitter/bookmark.md b/docs/integrations/block-integrations/twitter/bookmark.md
similarity index 100%
rename from docs/integrations/twitter/bookmark.md
rename to docs/integrations/block-integrations/twitter/bookmark.md
diff --git a/docs/integrations/twitter/follows.md b/docs/integrations/block-integrations/twitter/follows.md
similarity index 100%
rename from docs/integrations/twitter/follows.md
rename to docs/integrations/block-integrations/twitter/follows.md
diff --git a/docs/integrations/twitter/hide.md b/docs/integrations/block-integrations/twitter/hide.md
similarity index 100%
rename from docs/integrations/twitter/hide.md
rename to docs/integrations/block-integrations/twitter/hide.md
diff --git a/docs/integrations/twitter/like.md b/docs/integrations/block-integrations/twitter/like.md
similarity index 100%
rename from docs/integrations/twitter/like.md
rename to docs/integrations/block-integrations/twitter/like.md
diff --git a/docs/integrations/twitter/list_follows.md b/docs/integrations/block-integrations/twitter/list_follows.md
similarity index 100%
rename from docs/integrations/twitter/list_follows.md
rename to docs/integrations/block-integrations/twitter/list_follows.md
diff --git a/docs/integrations/twitter/list_lookup.md b/docs/integrations/block-integrations/twitter/list_lookup.md
similarity index 100%
rename from docs/integrations/twitter/list_lookup.md
rename to docs/integrations/block-integrations/twitter/list_lookup.md
diff --git a/docs/integrations/twitter/list_members.md b/docs/integrations/block-integrations/twitter/list_members.md
similarity index 100%
rename from docs/integrations/twitter/list_members.md
rename to docs/integrations/block-integrations/twitter/list_members.md
diff --git a/docs/integrations/twitter/list_tweets_lookup.md b/docs/integrations/block-integrations/twitter/list_tweets_lookup.md
similarity index 100%
rename from docs/integrations/twitter/list_tweets_lookup.md
rename to docs/integrations/block-integrations/twitter/list_tweets_lookup.md
diff --git a/docs/integrations/twitter/manage.md b/docs/integrations/block-integrations/twitter/manage.md
similarity index 100%
rename from docs/integrations/twitter/manage.md
rename to docs/integrations/block-integrations/twitter/manage.md
diff --git a/docs/integrations/twitter/manage_lists.md b/docs/integrations/block-integrations/twitter/manage_lists.md
similarity index 100%
rename from docs/integrations/twitter/manage_lists.md
rename to docs/integrations/block-integrations/twitter/manage_lists.md
diff --git a/docs/integrations/twitter/mutes.md b/docs/integrations/block-integrations/twitter/mutes.md
similarity index 100%
rename from docs/integrations/twitter/mutes.md
rename to docs/integrations/block-integrations/twitter/mutes.md
diff --git a/docs/integrations/twitter/pinned_lists.md b/docs/integrations/block-integrations/twitter/pinned_lists.md
similarity index 100%
rename from docs/integrations/twitter/pinned_lists.md
rename to docs/integrations/block-integrations/twitter/pinned_lists.md
diff --git a/docs/integrations/twitter/quote.md b/docs/integrations/block-integrations/twitter/quote.md
similarity index 100%
rename from docs/integrations/twitter/quote.md
rename to docs/integrations/block-integrations/twitter/quote.md
diff --git a/docs/integrations/twitter/retweet.md b/docs/integrations/block-integrations/twitter/retweet.md
similarity index 100%
rename from docs/integrations/twitter/retweet.md
rename to docs/integrations/block-integrations/twitter/retweet.md
diff --git a/docs/integrations/twitter/search_spaces.md b/docs/integrations/block-integrations/twitter/search_spaces.md
similarity index 100%
rename from docs/integrations/twitter/search_spaces.md
rename to docs/integrations/block-integrations/twitter/search_spaces.md
diff --git a/docs/integrations/twitter/spaces_lookup.md b/docs/integrations/block-integrations/twitter/spaces_lookup.md
similarity index 100%
rename from docs/integrations/twitter/spaces_lookup.md
rename to docs/integrations/block-integrations/twitter/spaces_lookup.md
diff --git a/docs/integrations/twitter/timeline.md b/docs/integrations/block-integrations/twitter/timeline.md
similarity index 100%
rename from docs/integrations/twitter/timeline.md
rename to docs/integrations/block-integrations/twitter/timeline.md
diff --git a/docs/integrations/twitter/tweet_lookup.md b/docs/integrations/block-integrations/twitter/tweet_lookup.md
similarity index 100%
rename from docs/integrations/twitter/tweet_lookup.md
rename to docs/integrations/block-integrations/twitter/tweet_lookup.md
diff --git a/docs/integrations/twitter/twitter.md b/docs/integrations/block-integrations/twitter/twitter.md
similarity index 100%
rename from docs/integrations/twitter/twitter.md
rename to docs/integrations/block-integrations/twitter/twitter.md
diff --git a/docs/integrations/twitter/user_lookup.md b/docs/integrations/block-integrations/twitter/user_lookup.md
similarity index 100%
rename from docs/integrations/twitter/user_lookup.md
rename to docs/integrations/block-integrations/twitter/user_lookup.md
diff --git a/docs/integrations/wolfram/llm_api.md b/docs/integrations/block-integrations/wolfram/llm_api.md
similarity index 100%
rename from docs/integrations/wolfram/llm_api.md
rename to docs/integrations/block-integrations/wolfram/llm_api.md
diff --git a/docs/integrations/youtube.md b/docs/integrations/block-integrations/youtube.md
similarity index 100%
rename from docs/integrations/youtube.md
rename to docs/integrations/block-integrations/youtube.md
diff --git a/docs/integrations/zerobounce/validate_emails.md b/docs/integrations/block-integrations/zerobounce/validate_emails.md
similarity index 100%
rename from docs/integrations/zerobounce/validate_emails.md
rename to docs/integrations/block-integrations/zerobounce/validate_emails.md
diff --git a/docs/integrations/guides/llm-providers.md b/docs/integrations/guides/llm-providers.md
new file mode 100644
index 0000000000..73d789b479
--- /dev/null
+++ b/docs/integrations/guides/llm-providers.md
@@ -0,0 +1,16 @@
+# LLM Providers
+
+There are several providers that AutoGPT users can use for running inference with LLM models.
+
+## Llama API
+
+Llama API is a Meta-hosted API service that helps you integrate Llama models quickly and efficiently. Using OpenAI compatibility endpoints, you can easily access the power of Llama models without the need for complex setup or configuration!
+
+Join the [waitlist](https://llama.developer.meta.com/?utm_source=partner-autogpt&utm_medium=readme) to get access!
+
+Try the Llama API provider by selecting any of the following LLM Model names from the AI blocks:
+
+* Llama-4-Scout-17B-16E-Instruct-FP8
+* Llama-4-Maverick-17B-128E-Instruct-FP8
+* Llama-3.3-8B-Instruct
+* Llama-3-70B-Instruct
diff --git a/docs/integrations/guides/voice-providers.md b/docs/integrations/guides/voice-providers.md
new file mode 100644
index 0000000000..450bed0676
--- /dev/null
+++ b/docs/integrations/guides/voice-providers.md
@@ -0,0 +1,22 @@
+# Voice Providers for D-ID
+
+This guide covers the voice providers you can use with the D-ID Create Talking Avatar Video block.
+
+## ElevenLabs
+
+1. Select any voice from the voice list: [https://api.elevenlabs.io/v1/voices](https://api.elevenlabs.io/v1/voices)
+2. Copy the `voice_id`
+3. Use it as a string in the `voice_id` field in the CreateTalkingAvatarClip Block
+
+## Microsoft Azure Voices
+
+1. Select any voice from the voice gallery: [https://speech.microsoft.com/portal/voicegallery](https://speech.microsoft.com/portal/voicegallery)
+2. Click on the "Sample code" tab on the right
+3. Copy the voice name, for example: `config.SpeechSynthesisVoiceName = "en-GB-AbbiNeural"`
+4. Use this string `en-GB-AbbiNeural` in the `voice_id` field in the CreateTalkingAvatarClip Block
+
+## Amazon Polly Voices
+
+1. Select any voice from the voice list: [https://docs.aws.amazon.com/polly/latest/dg/available-voices.html](https://docs.aws.amazon.com/polly/latest/dg/available-voices.html)
+2. Copy the voice name / ID
+3. Use it as string in the `voice_id` field in the CreateTalkingAvatarClip Block
diff --git a/docs/platform/block-sdk-guide.md b/docs/platform/block-sdk-guide.md
index 5b3eda5184..42fd883251 100644
--- a/docs/platform/block-sdk-guide.md
+++ b/docs/platform/block-sdk-guide.md
@@ -277,6 +277,50 @@ async def run(
token = credentials.api_key.get_secret_value()
```
+### Handling Files
+
+When your block works with files (images, videos, documents), use `store_media_file()`:
+
+```python
+from backend.data.execution import ExecutionContext
+from backend.util.file import store_media_file
+from backend.util.type import MediaFileType
+
+async def run(
+ self,
+ input_data: Input,
+ *,
+ execution_context: ExecutionContext,
+ **kwargs,
+):
+ # PROCESSING: Need local file path for tools like ffmpeg, MoviePy, PIL
+ local_path = await store_media_file(
+ file=input_data.video,
+ execution_context=execution_context,
+ return_format="for_local_processing",
+ )
+
+ # EXTERNAL API: Need base64 content for APIs like Replicate, OpenAI
+ image_b64 = await store_media_file(
+ file=input_data.image,
+ execution_context=execution_context,
+ return_format="for_external_api",
+ )
+
+ # OUTPUT: Return to user/next block (auto-adapts to context)
+ result = await store_media_file(
+ file=generated_url,
+ execution_context=execution_context,
+ return_format="for_block_output", # workspace:// in CoPilot, data URI in graphs
+ )
+ yield "image_url", result
+```
+
+**Return format options:**
+- `"for_local_processing"` - Local file path for processing tools
+- `"for_external_api"` - Data URI for external APIs needing base64
+- `"for_block_output"` - **Always use for outputs** - automatically picks best format
+
## Testing Your Block
```bash
diff --git a/docs/platform/contributing/oauth-integration-flow.md b/docs/platform/contributing/oauth-integration-flow.md
index dbc7a54be5..f6c3f7fd17 100644
--- a/docs/platform/contributing/oauth-integration-flow.md
+++ b/docs/platform/contributing/oauth-integration-flow.md
@@ -25,7 +25,7 @@ This document focuses on the **API Integration OAuth flow** used for connecting
### 2. Backend API Trust Boundary
- **Location**: Server-side FastAPI application
- **Components**:
- - Integration router (`/backend/backend/server/integrations/router.py`)
+ - Integration router (`/backend/backend/api/features/integrations/router.py`)
- OAuth handlers (`/backend/backend/integrations/oauth/`)
- Credentials store (`/backend/backend/integrations/credentials_store.py`)
- **Trust Level**: Trusted - server-controlled environment
diff --git a/docs/platform/new_blocks.md b/docs/platform/new_blocks.md
index d9d329ff51..114ff8d9a4 100644
--- a/docs/platform/new_blocks.md
+++ b/docs/platform/new_blocks.md
@@ -111,6 +111,71 @@ Follow these steps to create and test a new block:
- `graph_exec_id`: The ID of the execution of the agent. This changes every time the agent has a new "run"
- `node_exec_id`: The ID of the execution of the node. This changes every time the node is executed
- `node_id`: The ID of the node that is being executed. It changes every version of the graph, but not every time the node is executed.
+ - `execution_context`: An `ExecutionContext` object containing user_id, graph_exec_id, workspace_id, and session_id. Required for file handling.
+
+### Handling Files in Blocks
+
+When your block needs to work with files (images, videos, documents), use `store_media_file()` from `backend.util.file`. This function handles downloading, validation, virus scanning, and storage.
+
+**Import:**
+```python
+from backend.data.execution import ExecutionContext
+from backend.util.file import store_media_file
+from backend.util.type import MediaFileType
+```
+
+**The `return_format` parameter determines what you get back:**
+
+| Format | Use When | Returns |
+|--------|----------|---------|
+| `"for_local_processing"` | Processing with local tools (ffmpeg, MoviePy, PIL) | Local file path (e.g., `"image.png"`) |
+| `"for_external_api"` | Sending content to external APIs (Replicate, OpenAI) | Data URI (e.g., `"data:image/png;base64,..."`) |
+| `"for_block_output"` | Returning output from your block | Smart: `workspace://` in CoPilot, data URI in graphs |
+
+**Examples:**
+
+```python
+async def run(
+ self,
+ input_data: Input,
+ *,
+ execution_context: ExecutionContext,
+ **kwargs,
+) -> BlockOutput:
+ # PROCESSING: Need to work with file locally (ffmpeg, MoviePy, PIL)
+ local_path = await store_media_file(
+ file=input_data.video,
+ execution_context=execution_context,
+ return_format="for_local_processing",
+ )
+ # local_path = "video.mp4" - use with Path, ffmpeg, subprocess, etc.
+ full_path = get_exec_file_path(execution_context.graph_exec_id, local_path)
+
+ # EXTERNAL API: Need to send content to an API like Replicate
+ image_b64 = await store_media_file(
+ file=input_data.image,
+ execution_context=execution_context,
+ return_format="for_external_api",
+ )
+ # image_b64 = "data:image/png;base64,iVBORw0..." - send to external API
+
+ # OUTPUT: Returning result from block to user/next block
+ result_url = await store_media_file(
+ file=generated_image_url,
+ execution_context=execution_context,
+ return_format="for_block_output",
+ )
+ yield "image_url", result_url
+ # In CoPilot: result_url = "workspace://abc123" (persistent, context-efficient)
+ # In graphs: result_url = "data:image/png;base64,..." (for next block/display)
+```
+
+**Key points:**
+
+- `for_block_output` is the **only** format that auto-adapts to execution context
+- Always use `for_block_output` for block outputs unless you have a specific reason not to
+- Never manually check for `workspace_id` - let `for_block_output` handle the logic
+- The function handles URLs, data URIs, `workspace://` references, and local paths as input
### Field Types
diff --git a/docs/platform/ollama.md b/docs/platform/ollama.md
index 392bfabfe8..ecab9b8ae1 100644
--- a/docs/platform/ollama.md
+++ b/docs/platform/ollama.md
@@ -246,7 +246,7 @@ If you encounter any issues, verify that:
```bash
ollama pull llama3.2
```
-- If using a custom model, ensure it's added to the model list in `backend/server/model.py`
+- If using a custom model, ensure it's added to the model list in `backend/api/model.py`
#### Docker Issues
- Ensure Docker daemon is running: