# Overview Source: https://docs.envole.ai/api-reference/introduction Overview and authentication for the Envole API The Envole API provides a RESTful interface for building assistants. You can create session threads, post messages with mixed content, and stream real‑time updates as the agent works. ## Authentication All requests require: * `Authorization: Bearer ` – your API key * `X-Envole-User-Id: ` – user identifier; may represent an Envole user or an external ID ## Capabilities * Start new session threads and manage existing ones * Send messages containing text or files * Stream agent responses, tool approvals, and notifications via Server-Sent Events * Retrieve previous threads and messages Refer to the [Streaming](./streaming/index) section for event formats and SSE details. # Add Session Thread Message Source: https://docs.envole.ai/api-reference/session-thread/add-session-thread-message POST /api/assistants/threads/{threadId}/messages Adds a message to a session thread and streams events back using Server-Sent Events. Send a new message to a session thread and receive updates as it is processed. Responses are returned as Server-Sent Events that stream message processing updates. See the [Streaming](/api-reference/streaming/index) section for event types and payload formats. # Delete Session Thread Source: https://docs.envole.ai/api-reference/session-thread/delete-session-thread DELETE /api/assistants/threads/{threadId} Deletes a session thread by its ID. Remove a session thread. # Rename Session Thread Source: https://docs.envole.ai/api-reference/session-thread/rename-session-thread PUT /api/assistants/threads/{threadId} Renames a session thread. Rename a session thread. # Retrieve Session Thread Messages Source: https://docs.envole.ai/api-reference/session-thread/retrieve-session-thread-messages GET /api/assistants/threads/{threadId}/messages Retrieves messages for a given session thread. Get messages from a session thread. # Retrieve Session Threads Source: https://docs.envole.ai/api-reference/session-thread/retrieve-session-threads GET /api/assistants/threads/{agentId} Retrieves session threads for a given agent. Fetch session threads for a specific agent. # Start New Session Source: https://docs.envole.ai/api-reference/session-thread/start-new-session POST /api/assistants/threads Creates a new session thread for a given agent. Create a new session thread for an agent. # Agent Response Events Source: https://docs.envole.ai/api-reference/stream-events/agent-response The agent's answer is streamed back in chunks followed by a completion event. ### `AGENT_RESPONSE_CHUNK` Partial agent output. ```json { "type": "AGENT_RESPONSE_CHUNK", "eventId": "evt_2", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "hel", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:01" } } ``` ### `AGENT_RESPONSE_COMPLETE` Final agent output with the full response text. ```json { "type": "AGENT_RESPONSE_COMPLETE", "eventId": "evt_3", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "hello", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:02" } } ``` # Connection Events Source: https://docs.envole.ai/api-reference/stream-events/connection These events are sent when a streaming connection is established. ### `CONNECTION_ESTABLISHED` Emitted immediately after the SSE connection is set up. ```json { "type": "CONNECTION_ESTABLISHED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` # Error Events Source: https://docs.envole.ai/api-reference/stream-events/error If processing fails, an `ERROR` event is emitted and the stream closes. ```json { "type": "ERROR", "eventId": "evt_error", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "timeout", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:05" } } ``` # Overview Source: https://docs.envole.ai/api-reference/stream-events/index Server-sent events emitted while processing session thread messages All message requests stream structured events over **Server-Sent Events (SSE)**. Each `data:` line contains an `SseEvent` object: ```json { "type": "AGENT_RESPONSE_CHUNK", "eventId": "evt_123", "threadId": "thread_456", "requestId": "req_789", "eventMessage": { "agent": { "name": "Demo Agent", "id": "agent_1" }, "content": "partial text", "collaborationId": null, "activeAssistantCollaborationRequired": false, "toolExecutionApprovalRequest": [], "timestamp": "2024-01-01T12:00:02Z" } } ``` Events are grouped into categories. Explore the sub‑pages for the full list of events and example payloads: * [Connection](./connection) * [Message](./message) * [Agent Response](./agent-response) * [Tool Approval](./tool-approval) * [Notifications](./notifications) * [Error](./error) # Message Events Source: https://docs.envole.ai/api-reference/stream-events/message Events acknowledging receipt of a message. ### `MESSAGE_RECEIVED` Sent after the server accepts the user's message. ```json { "type": "MESSAGE_RECEIVED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "Hi what can you do for me", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` # Agent Thinking Notifications Source: https://docs.envole.ai/api-reference/stream-events/notifications/agent-thinking Notifications when the assistant begins and ends internal reasoning. Subscribe for insight into the assistant's thought process. ### `NOTIFICATION_AGENT_THINKING_STARTED` Agent began internal processing. ```json { "type": "NOTIFICATION_AGENT_THINKING_STARTED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "agent began internal processing", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_AGENT_THINKING_COMPLETE` Agent finished internal processing. ```json { "type": "NOTIFICATION_AGENT_THINKING_COMPLETE", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "agent finished internal processing", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` # Context Memory Notifications Source: https://docs.envole.ai/api-reference/stream-events/notifications/context-memories Notifications about problems retrieving stored context or memories. Subscribe to detect and debug memory-related failures. ### `NOTIFICATION_CONTEXT_MEMORIES_RETRIEVAL_FAILED` Retrieval of context memories failed. ```json { "type": "NOTIFICATION_CONTEXT_MEMORIES_RETRIEVAL_FAILED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "retrieval of context memories failed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` # Notification Events Source: https://docs.envole.ai/api-reference/stream-events/notifications/index All notification events are prefixed with `NOTIFICATION_`. Related events are grouped below: * [Tool Execution](./tool-execution) * [Agent Thinking](./agent-thinking) * [Knowledge Retrieval](./knowledge-retrieval) * [Request Orchestration](./request-orchestration) * [Plan Orchestration](./plan-orchestration) * [Multi-Assistant Collaboration](./multi-assistant) * [Context Memories](./context-memories) # Knowledge Retrieval Notifications Source: https://docs.envole.ai/api-reference/stream-events/notifications/knowledge-retrieval Notifications detailing the lifecycle of knowledge lookups, including progress, completion, cache reuse, and failures. Subscribe to monitor how data is gathered. ### `NOTIFICATION_KNOWLEDGE_RETRIEVAL_INITIATED` Knowledge retrieval started. ```json { "type": "NOTIFICATION_KNOWLEDGE_RETRIEVAL_INITIATED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "knowledge retrieval started", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_KNOWLEDGE_RETRIEVAL_IN_PROGRESS` Knowledge retrieval in progress. ```json { "type": "NOTIFICATION_KNOWLEDGE_RETRIEVAL_IN_PROGRESS", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "knowledge retrieval in progress", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_KNOWLEDGE_RETRIEVAL_COMPLETED` Knowledge retrieval completed. ```json { "type": "NOTIFICATION_KNOWLEDGE_RETRIEVAL_COMPLETED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "knowledge retrieval completed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_KNOWLEDGE_RETRIEVAL_FAILED` Knowledge retrieval failed. ```json { "type": "NOTIFICATION_KNOWLEDGE_RETRIEVAL_FAILED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "knowledge retrieval failed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_KNOWLEDGE_RETRIEVAL_DUPLICATED_CACHED` Reused cached knowledge. ```json { "type": "NOTIFICATION_KNOWLEDGE_RETRIEVAL_DUPLICATED_CACHED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "reused cached knowledge", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` # Multi-Assistant Collaboration Notifications Source: https://docs.envole.ai/api-reference/stream-events/notifications/multi-assistant Notifications about collaborative sessions involving multiple assistants. Subscribe to track coordination events and unified responses. ### `NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_STARTED` Multi-assistant collaboration started. ```json { "type": "NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_STARTED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "multi-assistant collaboration started", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_ASSISTANT_RESPONSE_IN_PROGRESS` Assistant response in progress during collaboration. ```json { "type": "NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_ASSISTANT_RESPONSE_IN_PROGRESS", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "assistant response in progress during collaboration", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_ASSISTANT_RESPONSE_COMPLETED` Assistant response completed. ```json { "type": "NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_ASSISTANT_RESPONSE_COMPLETED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "assistant response completed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_UNIFIED_RESPONSE_STARTED` Unified response synthesis started. ```json { "type": "NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_UNIFIED_RESPONSE_STARTED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "unified response synthesis started", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_NO_UNIFIED_RESPONSE_REQUIRED` No unified response needed. ```json { "type": "NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_NO_UNIFIED_RESPONSE_REQUIRED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "no unified response needed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_COMPLETED` Collaboration completed. ```json { "type": "NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_COMPLETED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "collaboration completed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_FAILED` Collaboration failed. ```json { "type": "NOTIFICATION_MULTI_ASSISTANT_COLLABORATION_FAILED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "collaboration failed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` # Plan Orchestration Notifications Source: https://docs.envole.ai/api-reference/stream-events/notifications/plan-orchestration Notifications emitted while constructing, reviewing, and executing plans. Subscribe to follow complex or simple orchestration steps as they unfold. ### `NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_INITIATED` Complex plan creation started. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_INITIATED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "complex plan creation started", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_IN_PROGRESS` Complex plan creation in progress. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_IN_PROGRESS", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "complex plan creation in progress", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_COMPLETED` Complex plan creation completed. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_COMPLETED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "complex plan creation completed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_REVIEW_INITIATED` Review of complex plan started. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_REVIEW_INITIATED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "review of complex plan started", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_REVIEW_IN_PROGRESS` Review of complex plan in progress. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_REVIEW_IN_PROGRESS", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "review of complex plan in progress", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_REVIEW_COMPLETED` Review of complex plan completed. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_COMPLEX_REVIEW_COMPLETED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "review of complex plan completed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_KNOWLEDGE_BASE_INITIATED` Knowledge-base planning started. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_KNOWLEDGE_BASE_INITIATED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "knowledge-base planning started", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_KNOWLEDGE_BASE_IN_PROGRESS` Knowledge-base planning in progress. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_KNOWLEDGE_BASE_IN_PROGRESS", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "knowledge-base planning in progress", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_KNOWLEDGE_BASE_COMPLETED` Knowledge-base planning completed. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_KNOWLEDGE_BASE_COMPLETED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "knowledge-base planning completed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_KNOWLEDGE_RETRIEVAL_INITIATED` Planning triggered knowledge retrieval. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_KNOWLEDGE_RETRIEVAL_INITIATED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "planning triggered knowledge retrieval", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_TOOL_USAGE_INITIATED` Tool usage planning started. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_TOOL_USAGE_INITIATED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "tool usage planning started", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_TOOL_USAGE_IN_PROGRESS` Tool usage planning in progress. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_TOOL_USAGE_IN_PROGRESS", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "tool usage planning in progress", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_TOOL_USAGE_COMPLETED` Tool usage planning completed. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_TOOL_USAGE_COMPLETED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "tool usage planning completed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_REFLECTION_INITIATED` Reflection phase started. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_REFLECTION_INITIATED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "reflection phase started", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_REFLECTION_ABORTED` Reflection aborted. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_REFLECTION_ABORTED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "reflection aborted", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_REFLECTION_FAILED` Reflection failed. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_REFLECTION_FAILED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "reflection failed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_REFLECTION_COMPLETED` Reflection completed. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_REFLECTION_COMPLETED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "reflection completed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_COLLABORATION_INITIATED` Collaboration planning started. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_COLLABORATION_INITIATED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "collaboration planning started", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_COLLABORATION_IN_PROGRESS` Collaboration planning in progress. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_COLLABORATION_IN_PROGRESS", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "collaboration planning in progress", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_PLAN_ORCHESTRATION_COLLABORATION_COMPLETED` Collaboration planning completed. ```json { "type": "NOTIFICATION_PLAN_ORCHESTRATION_COLLABORATION_COMPLETED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "collaboration planning completed", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` # Request Orchestration Notifications Source: https://docs.envole.ai/api-reference/stream-events/notifications/request-orchestration Notifications about how requests are delegated across capabilities, knowledge, or assistants. Subscribe to understand routing decisions and orchestration context. ### `NOTIFICATION_REQUEST_ORCHESTRATION_SIMPLE` Simple request orchestration. ```json { "type": "NOTIFICATION_REQUEST_ORCHESTRATION_SIMPLE", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "simple request orchestration", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_REQUEST_ORCHESTRATION_COMPLEX` Complex request orchestration. ```json { "type": "NOTIFICATION_REQUEST_ORCHESTRATION_COMPLEX", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "complex request orchestration", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_REQUEST_ORCHESTRATION_CAPABILITIES` Orchestrating based on capabilities. ```json { "type": "NOTIFICATION_REQUEST_ORCHESTRATION_CAPABILITIES", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "orchestrating based on capabilities", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_REQUEST_ORCHESTRATION_KNOWLEDGE_BASE` Orchestrating knowledge-base use. ```json { "type": "NOTIFICATION_REQUEST_ORCHESTRATION_KNOWLEDGE_BASE", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "orchestrating knowledge-base use", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_REQUEST_ORCHESTRATION_TOOL_USAGE` Orchestrating tool usage. ```json { "type": "NOTIFICATION_REQUEST_ORCHESTRATION_TOOL_USAGE", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "orchestrating tool usage", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_REQUEST_ORCHESTRATION_COLLABORATION` Orchestrating collaboration. ```json { "type": "NOTIFICATION_REQUEST_ORCHESTRATION_COLLABORATION", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "orchestrating collaboration", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` # Tool Execution Notifications Source: https://docs.envole.ai/api-reference/stream-events/notifications/tool-execution Notifications about the lifecycle of tool runs, including start, approval, progress, and completion. Subscribe to monitor and intervene in tool usage. ### `NOTIFICATION_TOOL_EXECUTION_INITIATED` Tool execution started. ```json { "type": "NOTIFICATION_TOOL_EXECUTION_INITIATED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "tool execution started", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_TOOL_EXECUTION_IN_PROGRESS` Tool execution in progress. ```json { "type": "NOTIFICATION_TOOL_EXECUTION_IN_PROGRESS", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "tool execution in progress", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_TOOL_EXECUTION_APPROVAL_REQUIRED` Tool execution requires approval. ```json { "type": "NOTIFICATION_TOOL_EXECUTION_APPROVAL_REQUIRED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "tool execution requires approval", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_TOOL_EXECUTION_APPROVAL_ACCEPTED` Tool execution approved. ```json { "type": "NOTIFICATION_TOOL_EXECUTION_APPROVAL_ACCEPTED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "tool execution approved", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_TOOL_EXECUTION_APPROVAL_DENIED` Tool execution denied. ```json { "type": "NOTIFICATION_TOOL_EXECUTION_APPROVAL_DENIED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "tool execution denied", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` ### `NOTIFICATION_TOOL_EXECUTION_APPROVAL_ABORTED` Tool execution aborted with feedback. ```json { "type": "NOTIFICATION_TOOL_EXECUTION_APPROVAL_ABORTED", "eventId": "evt_1", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "tool execution aborted with feedback", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": null, "timestamp": "2025-08-12T00:00:00" } } ``` # Tool Approval Events Source: https://docs.envole.ai/api-reference/stream-events/tool-approval If an agent requires human approval to execute a tool, a `TOOL_EXECUTION_APPROVAL_REQUEST` event is emitted. ```json { "type": "TOOL_EXECUTION_APPROVAL_REQUEST", "eventId": "evt_5", "threadId": "thread_456", "requestId": "req_1", "eventMessage": { "agent": null, "content": "", "collaborationId": null, "activeAssistantCollaborationRequired": null, "toolExecutionApprovalRequest": [ { "toolId": "tool_123", "toolName": "google_calendar_create_event", "toolProvider": "GOOGLE_CALENDAR", "toolCategory": "CALENDAR", "toolExecutionId": "exec_123", "toolExecutionBatchId": "batch_456", "toolMemoryId": "mem_789", "toolArguments": { "event_title": "Project Review Meeting", "start_time": "2024-01-15T14:00:00Z", "end_time": "2024-01-15T15:00:00Z", "attendees": "john@company.com,mary@company.com", "location": "Conference Room A" }, "approvalResult": "PENDING_HUMAN_APPROVAL" } ], "timestamp": "2025-08-12T00:00:03" } } ``` # Human-in-the-Loop Source: https://docs.envole.ai/getting-started/human-in-the-loop/index Stay in control when assistants take actions on your behalf Human-in-the-Loop is Envole's way of ensuring you stay in complete control when your assistants want to take actions that affect your systems, data, or communications. Instead of assistants acting autonomously, they ask for your explicit approval before executing important tasks. Think of it as having a thoughtful assistant who checks with you before sending emails, creating calendar events, updating project management tools, or making changes to documents. You get the efficiency of AI automation with the safety and control of human oversight. ## Why Human-in-the-Loop Matters **Safety First**: Prevents assistants from taking unintended actions that could affect your work, relationships, or data. **Maintain Control**: You decide what actions are appropriate for each situation, maintaining authority over your tools and communications. **Learn and Trust**: As you see what assistants want to do, you build trust in their judgment and can provide feedback to improve future suggestions. **Compliance**: Ensures sensitive actions meet your organization's approval requirements and policies. ## How Tool Approval Works When your assistant determines that a task requires taking an action—like sending an email, creating a calendar event, or updating a project status—it will pause and ask for your approval instead of acting immediately. ### Step 1: Assistant Identifies Actions Needed Your assistant analyzes your request and determines what specific actions it needs to take. For example, if you ask it to "schedule a follow-up meeting with the client," it identifies that it needs to: * Create a calendar event * Send invitation emails to attendees * Possibly update your CRM with the meeting details ### Step 2: Approval Request Appears Instead of taking these actions immediately, your assistant presents them to you for review and approval. !\[Tool Approval Interface - Image 1] **What you'll see:** * Clear description of each action the assistant wants to take * Specific details like email recipients, calendar event details, or document changes * Preview of exactly what will happen if you approve * Options to approve, deny, or provide feedback ### Step 3: Review and Decide You have three options for each action: **Approve**: The assistant will execute the action exactly as proposed. **Deny**: The assistant will skip this action but continue with others you approve. **Provide Feedback**: Stop the process and give the assistant feedback about why the action isn't quite right, allowing it to revise its approach. !\[Approval Options - Image 2] ### Step 4: Batch Decision Making Often, assistants will propose multiple related actions at once. Envole presents these as a group so you can: * See how actions work together * Make decisions about the entire workflow * Ensure all actions align with your intentions !\[Batch Approval Interface - Image 3] **Key insight**: Related actions are grouped together because they often depend on each other. For example, if you're organizing a project kickoff, the assistant might want to create the meeting, send invitations, and update the project timeline all at once. ### Step 5: Execution and Confirmation Once you approve actions, your assistant executes them and provides confirmation of what was completed. !\[Execution Confirmation - Image 4] **You'll receive:** * Confirmation that approved actions were successfully completed * Details of what was accomplished (emails sent, events created, etc.) * Information about any actions that couldn't be completed and why ## Common Human-in-the-Loop Scenarios ### Email and Communication * **Scenario**: "Send a project update to the team" * **Approval needed**: Review recipient list, email content, attachments * **Why important**: Ensures the right people get the right message at the right time ### Calendar Management * **Scenario**: "Schedule meetings with our key clients" * **Approval needed**: Meeting times, attendee lists, meeting locations or video links * **Why important**: Prevents scheduling conflicts and ensures appropriate attendees ### Project Management * **Scenario**: "Update project status based on our team standup" * **Approval needed**: Status changes, task assignments, deadline updates * **Why important**: Maintains accurate project tracking and team alignment ### Document Creation and Updates * **Scenario**: "Create a proposal based on our discussion" * **Approval needed**: Document content, sharing permissions, storage location * **Why important**: Ensures documents meet your standards and are shared appropriately ### Tool Integrations * **Scenario**: "Create Jira tickets for the bugs we discussed" * **Approval needed**: Ticket details, assignees, priority levels * **Why important**: Ensures accurate issue tracking and proper workflow management ## Making Approval Decisions ### What to Look For **Accuracy**: Are the details correct? Check recipients, dates, amounts, and other specifics. **Appropriateness**: Is this the right action for the situation? Consider timing, audience, and context. **Completeness**: Does the action accomplish what you intended? Are any important details missing? **Impact**: What are the consequences of this action? Who will be affected and how? ### When to Approve * Details are accurate and appropriate * The action aligns with your goals * Timing is right for the intended outcome * You're comfortable with the potential impact ### When to Deny * Some details need adjustment but the overall approach is wrong * You want the assistant to try a different approach * The timing isn't right for this action * You prefer to handle this manually ### When to Provide Feedback * The approach is close but needs refinement * Important context or constraints were missed * You want to guide the assistant toward a better solution * The action needs significant modification ## Best Practices for Human-in-the-Loop ### Be Specific in Your Feedback When providing feedback, help your assistant understand not just what to change, but why: * ❌ "This email doesn't look right" * ✅ "The email tone is too formal for this client relationship, and we should include the budget discussion we had last week" ### Consider Batch Dependencies When reviewing multiple actions, think about how they work together: * If you approve the meeting but deny the email invitation, how will attendees know about it? * If you approve updating the project status but deny notifying stakeholders, will important people be left out of the loop? ### Use Approval Patterns As you work with your assistants, you'll develop patterns for what you typically approve or modify: * Always review external communications before sending * Auto-approve internal calendar bookings during specific hours * Always check budget-related updates before execution ### Provide Context for Better Future Suggestions The more context you provide in your feedback, the better your assistant becomes at making appropriate suggestions: * Explain your preferences for different types of communications * Share information about team dynamics or client relationships * Clarify organizational policies or constraints ## Benefits of Human-in-the-Loop **Builds Trust**: You see exactly what your assistant wants to do before it happens, building confidence in AI assistance. **Improves Over Time**: Your feedback helps assistants learn your preferences and make better suggestions. **Prevents Mistakes**: Catches potential issues before they impact your work or relationships. **Maintains Standards**: Ensures all AI-generated actions meet your quality and appropriateness standards. **Enables Learning**: You understand what tasks assistants can handle and how they approach different challenges. ## What's Next? Congratulations! You now understand all the key concepts that make Envole powerful: Team Personal Assistants, Sub-Assistants, Multi-Assistant Collaboration, and Human-in-the-Loop approval. You're ready to start transforming how your team works. Start your free trial and experience intelligent team assistance ## Dive Deeper Learn how to integrate Human-in-the-Loop into your applications See how Envole fits your team's specific needs # Multi-Assistant Collaboration Source: https://docs.envole.ai/getting-started/multi-assistant-collaboration/index Bring together expertise from multiple assistants with simple @-mentions Sometimes one assistant isn't enough. When you're tackling complex challenges that require diverse expertise—like launching a product that needs both technical and marketing insights, or solving a customer issue that spans support and sales—Envole lets you bring the right specialists together in one seamless conversation. The magic of multi-assistant collaboration is its simplicity: just @-mention the assistants you need, and Envole coordinates everything behind the scenes to deliver comprehensive, well-rounded responses. ## Why Collaborate with Multiple Assistants? **Get Diverse Perspectives**: Different assistants bring specialized knowledge and unique viewpoints to your challenges, ensuring you don't miss important considerations. **Save Time**: Instead of having separate conversations with different assistants and manually combining their insights, get everything you need in one comprehensive response. **Improve Quality**: Multiple perspectives often lead to better solutions, catching potential issues or opportunities that a single viewpoint might miss. **Ensure Completeness**: Complex projects benefit from cross-functional input—collaboration ensures all aspects are covered. ## How Multi-Assistant Collaboration Works ### Step 1: Discover Available Assistants When you're in any conversation, simply type the @ symbol to see all the assistants available in your organization. **What you'll see:** * Your Team Personal Assistant (always available) * Sub-Assistants created by your team * Published assistants from other teams * Specialized assistants for different functions (sales, marketing, engineering, etc.) Each assistant has a clear name that indicates their specialization, making it easy to choose the right expertise for your request. ### Step 2: Mention Multiple Assistants Naturally Write your request in natural language and @-mention the assistants whose expertise you need. There's no special syntax to remember—just communicate as you normally would. **Example scenarios:** * "@sales-assistant @marketing-assistant help me create a go-to-market strategy for our new feature" * "@engineering-assistant @product-assistant review this technical specification and suggest improvements" * "@support-assistant @billing-assistant help resolve this customer's payment and service issue" ### Step 3: Automatic Coordination Once Envole detects multiple assistant mentions, it automatically initiates the collaboration process. The system: * Ensures all assistants understand the full context * Coordinates their responses to complement each other * Manages the conversation flow * Presents a unified, comprehensive response You don't need to manage anything—just wait for the collaborative response. ### Step 4: Receive Comprehensive Insights The result is a response that combines specialized expertise from all mentioned assistants. You'll see: * **Clear attribution**: Which assistant contributed which insights * **Complementary perspectives**: How different viewpoints address your request * **Unified recommendations**: Coordinated advice that works together * **Follow-up coordination**: Your primary assistant often synthesizes everything into actionable next steps ## Real-World Collaboration Examples ### Product Launch Planning **Request**: "@product-assistant @marketing-assistant @sales-assistant help me plan the launch for our new analytics dashboard" **Result**: * Product assistant provides technical specifications and feature highlights * Marketing assistant suggests positioning, messaging, and campaign strategies * Sales assistant offers pricing insights, competitive analysis, and sales enablement needs * Unified response with coordinated timeline and responsibilities ### Customer Issue Resolution **Request**: "@support-assistant @engineering-assistant this customer is experiencing slow query performance" **Result**: * Support assistant provides customer context, impact assessment, and communication templates * Engineering assistant analyzes technical logs, identifies root causes, and suggests fixes * Coordinated response with both immediate customer communication and technical resolution ### Content Creation **Request**: "@content-assistant @brand-assistant create a blog post about our security features" **Result**: * Content assistant provides structure, SEO optimization, and writing best practices * Brand assistant ensures tone, messaging, and visual guidelines alignment * Unified draft that meets both content quality and brand standards ## When to Use Multi-Assistant Collaboration **Cross-Functional Projects**: When your task requires input from multiple departments or specializations. **Complex Problem-Solving**: When challenges need diverse types of expertise to solve effectively. **Comprehensive Planning**: When creating strategies, documents, or plans that benefit from multiple perspectives. **Risk Assessment**: When you want different viewpoints to identify potential issues or opportunities. **Learning and Exploration**: When entering unfamiliar territory and needing to understand various aspects of a topic. ## Best Practices for Effective Collaboration ### Be Specific About Your Needs Instead of vague requests, provide context about what you're trying to achieve: * ❌ "Help me with this project" * ✅ "Help me create a customer onboarding process that reduces support tickets while improving user satisfaction" ### Choose the Right Mix of Assistants Think strategically about what types of expertise your request requires: * **For product decisions**: Product + Engineering + Design * **For customer issues**: Support + Sales + Product * **For content creation**: Content + Brand + Marketing * **For process improvement**: Operations + relevant functional teams ### Provide Relevant Context The more context you share, the better assistants can tailor their collaborative response: * Share relevant documents, links, or background information * Mention constraints, deadlines, or specific requirements * Explain the broader goal, not just the immediate task ### Ask Follow-Up Questions If the collaborative response raises new questions or you need deeper insight: * Continue the conversation naturally * Mention additional assistants if new expertise is needed * Ask for clarification on specific aspects ## Collaboration vs. Individual Assistance **Use individual assistants when:** * You need focused expertise in one area * The task is straightforward and doesn't require multiple perspectives * You're iterating on work within a single domain **Use multi-assistant collaboration when:** * Your challenge spans multiple disciplines * You need comprehensive coverage of a complex topic * You want to validate ideas across different functional areas * You're planning something that affects multiple teams ## What's Next? Now that you understand how to leverage multiple assistants working together, you're ready to explore another powerful feature: understanding how Human-in-the-Loop approval works when assistants need your input before taking actions. Understand how Envole ensures you stay in control when assistants take actions ## Ready to Try Multi-Assistant Collaboration? Try @-mentions with your team's assistants Explore advanced collaboration features # Sub Assistants Source: https://docs.envole.ai/getting-started/sub-assistants/index Sub Assistants help your team automate granular work ### What are Sub-Assistants? Sub-assistants are focused, user-created helpers designed to automate and streamline repeatable team or individual workflows. Built using a no-code workflow builder, they let anyone—from product managers to sales reps—extend the power of their Team PA with specialized, on-demand automation. *** ### What do Sub-Assistants Do? * Automate routine or repetitive tasks (e.g., summarizing tickets, generating campaign briefs, drafting reports). * Standardize processes across your team, ensuring consistency and quality. * Save time by reducing manual work, so teams spend more time on high-value activities. * Provide templates for common tasks that can be customized and shared. *** ### How Do Sub-Assistants Work? * Created and configured by users (not admins) using a no-code workflow builder. * Can be built from scratch or by customizing templates for specific team needs. * Activated on demand—users interact directly through the dashboard or chat interface. * Can be personal (just for you) or published and shared across the team. * Sub-assistants do not work in the background; they require user interaction to run. *** ### Example Sub-Assistant Templates * **Marketing: Campaign Brief Generator** *What it does:* Converts campaign ideas into structured briefs, gathering goals, assets, and timelines from recent Slack discussions or emails. *How it helps:* Speeds up campaign planning, ensures all requirements are captured, and centralizes information for approvals. * **Sales: Lead Research Assistant** *What it does:* Collects lead data from CRM, LinkedIn, and recent emails, compiling a summary for each prospect. *How it helps:* Saves sales reps hours of manual research and ensures every conversation is informed by the latest context. * **Support: Ticket Summarizer** *What it does:* Summarizes new support tickets and highlights urgent issues for triage. *How it helps:* Reduces triage time, ensures nothing is missed, and surfaces critical cases instantly. * **Product: PRD Drafter** *What it does:* Turns meeting notes and feature requests into draft Product Requirement Documents. *How it helps:* Standardizes PRD creation and accelerates product planning. * **Content: Social Post Composer** *What it does:* Drafts social media posts or email copy based on product updates or marketing campaigns. *How it helps:* Maintains message consistency and speeds up content creation. * **Operations: Onboarding Checklist Builder** *What it does:* Generates personalized onboarding checklists for new hires, integrating tasks from HR, IT, and team managers. *How it helps:* Ensures nothing is forgotten and streamlines the onboarding process. *** ### Collaboration Features * Sub-assistants can be shared and published for team-wide use, enabling standardization and faster onboarding. * Can work in conjunction with Team PAs—PAs may call sub-assistants for specific tasks as part of a larger workflow. * Sub-assistants can cross-collaborate between teams when published beyond their original group. *** ### How are Sub-Assistants Different from Team PAs? Sub-assistants and Team PAs play distinct but complementary roles. Here’s how they compare: | Feature/Aspect | Team Personal Assistants (PAs) | Sub-Assistants (Sub-Agents) | | -------------------- | ------------------------------------------------------------- | ----------------------------------------------------------- | | Creation & Ownership | Provisioned/administered by organization; not user-built | Built and published by users via no-code workflow builder | | Core Role | Dedicated, role-focused team orchestrator | Task automation for specific, repeatable workflows | | Proactivity | Proactive summaries, nudges, and orchestration | User-driven and activated on demand | | Scope | Dedicated to teams but cross-functional and organization-wide | Team-focused, but can be shared or published to other teams | | Communication | Cross-functional via @mentions (e.g., Product PA to Eng PA) | Collaborate with PAs and other sub-assistants; team-driven | | Customization | Configured by admins; not user-built | Fully customizable and template-driven by any user | | Collaboration | Calls sub-assistants as part of orchestrating team workflows | Can be called by PAs, users, or shared between teams | #### Core Role of the Team PA: The Team PA is the dedicated, always-on orchestrator for your team. Configured by admins, it proactively organizes information, syncs tools, manages meetings, and coordinates workflows. PAs can communicate with other PAs across departments, providing a true cross-functional nervous system for the organization. *** ### Example Workflow After a marketing campaign meeting, a user triggers the Campaign Brief Generator to capture all requirements and assets. The Team PA then uses the Social Post Composer sub-assistant to draft announcement posts, while the Sales Lead Research Assistant is used by a rep to prep for follow-up calls. The Team PA coordinates, ensuring every artifact is shared and synchronized with the right tools and teams. *** ### Best Practices for Using Sub-Assistants * Start with templates—customize them to fit your team’s frequent tasks. * Publish and share your most useful sub-assistants so the whole team benefits. * Combine sub-assistants with Team PAs for end-to-end workflow automation. * Regularly review usage to identify new automation opportunities. * Iterate on sub-assistants to ensure they stay relevant as your team’s needs evolve. *** ## What's Next? Now that you understand both Team Personal Assistants and Sub-Assistants, you're ready to discover one of Envole's most powerful features: how these assistants can collaborate with each other to tackle complex challenges. Learn how to bring multiple assistants together using simple @-mentions ## Ready to Build Your First Sub-Assistant? Use the no-code workflow builder to create your first assistant Dive deeper into Sub-Assistant creation and deployment # Team Personal Assistants Source: https://docs.envole.ai/getting-started/team-personal-assistants/index Team Personal Assistants keep your teams organized Your Team Personal Assistant (PA) is like a real-life PA dedicated to keeping your entire team organized, informed, and moving forward—without the usual chaos of endless meetings and scattered tools. Each team gets its own PA that connects directly to the tools and knowledge sources your team already uses, such as Jira, Slack, Notion, and Google Drive. #### What does a Team PA do? * Brings together updates, tasks, documents, and action items from all your key tools and channels—no more manual tracking or context switching. * Surfaces the most relevant information for your team at the right time. * Proactively generates meeting agendas based on activity and context. * Keeps systems in sync by letting you push or update tasks and documents across platforms. * Flags blockers, dependencies, and risks before they slow your team down. #### How does the Team PA deliver this information? The PA powers your team dashboard, surfacing information through a set of specialized widgets. Each widget has a unique role, designed to reduce overhead and empower your team: *** #### Widget-by-Widget Breakdown **Daily Summary** * **What it does:** Presents a personalized, role-specific snapshot of the day’s top activities, unresolved blockers, achievements, and actionable nudges. * **How it helps:** Ensures you start every day focused on what matters most, surfacing the most urgent updates and activities. **Goals & Projects** * **What it does:** Offers a real-time overview of all team goals and active projects, with clear status indicators (on track, at risk, needs attention) and progress bars. * **How it helps:** Lets you drill into any goal or project for deeper context, quickly spot risks or blockers, and keeps everyone aligned on priorities. **Upcoming Meetings** * **What it does:** Lists all scheduled meetings, with proactively generated agendas crafted from recent standup notes, Slack conversations, or open action items. * **How it helps:** Ensures every meeting is actionable and focused, with clear objectives and linked tasks or goals for seamless follow-up. **Tasks** * **What it does:** Surfaces action items from anywhere—standups, Slack, email, or meetings. Tasks can be synchronized instantly into project management and development tools, like Jira, Linear, or GitHub. * **How it helps:** Eliminates busywork and duplicate entry, keeps all systems updated in real time, and ensures nothing falls through the cracks. **Documents** * **What it does:** Proactively creates and surfaces document drafts triggered by meetings, conversations, or standups (like API specs, PRDs, or technical docs). Allows you to iterate further and sync the latest version to Notion, Confluence, or other knowledge bases. * **How it helps:** Ensures everyone is working from the latest version, reduces manual file management, and makes knowledge accessible to all. **Latest Meeting Reports** * **What it does:** Provides concise summaries and highlights from recent meetings. Each report links directly to relevant follow-up tasks or documents and is transparently sourced. * **How it helps:** Makes next steps clear and traceable, so decisions and follow-ups are never lost. **Milestones** * **What it does:** Chronologically lists upcoming deadlines and key deliverables, with status and risk indicators for each. * **How it helps:** Ensures you never miss a critical deadline and can quickly address anything at risk by diving into related projects or tasks. **Latest Insights** * **What it does:** Surfaces trends, blockers, team health signals, and analytics, all transparently backed by their source (e.g., surveys, project updates, system analytics). * **How it helps:** Enables proactive, data-driven decisions and gives you real-time visibility on team health and workflow trends. *** **Always-on, always accessible:** Your Team PA is always available as a chat on the right side of your workspace. You can ask questions, request updates, or collaborate in real time—making the PA an ever-present partner in your team's success. *** ## What's Next? Now that you understand how Team Personal Assistants orchestrate your team's workflow, let's explore how you can extend their capabilities with specialized Sub-Assistants that automate specific tasks and workflows. Learn how to create and use specialized assistants for automating specific workflows ## Ready to Experience Team PAs? Get your Team Personal Assistant set up today Learn how Team PAs can transform your specific workflows # Platform Tour Source: https://docs.envole.ai/getting-started/tour/index Discover how Envole transforms team productivity Welcome to your guided tour of Envole! Let's explore how the platform brings AI-powered assistance directly into your team's daily workflow through an intuitive dashboard experience. ## Your Team Dashboard When you log into Envole, you're greeted by your personalized team dashboard. This isn't just another project management interface—it's an intelligent workspace powered by your Team Personal Assistant (PA) that understands your team's context and priorities. The dashboard is organized into intelligent widgets that surface the most relevant information for your team. Each widget is powered by your Team PA, which continuously analyzes your connected tools and conversations to present actionable insights. ## Dashboard Widgets Overview Your Team PA powers the dashboard through specialized widgets, each designed to reduce overhead and keep your team focused: **Daily Summary Widget** Your day starts with a personalized snapshot of top activities, unresolved blockers, achievements, and actionable nudges. No more hunting through multiple tools to understand what matters most. **Goals & Projects Widget** Real-time overview of all team goals and active projects with clear status indicators (on track, at risk, needs attention). Drill into any project for deeper context and quickly spot potential issues. **Upcoming Meetings Widget** Lists scheduled meetings with proactively generated agendas. Your Team PA crafts these agendas from recent standup notes, Slack conversations, and open action items, ensuring every meeting is focused and actionable. **Tasks Widget** Surfaces action items from everywhere—standups, Slack, email, or meetings. Tasks sync instantly with your project management tools like Jira, Linear, or GitHub, eliminating duplicate entry and ensuring nothing falls through the cracks. **Documents Widget** Your PA proactively creates document drafts triggered by meetings or conversations (like API specs, PRDs, or technical docs). Iterate on these drafts and sync the latest versions to Notion, Confluence, or other knowledge bases. **Latest Meeting Reports Widget** Concise summaries and highlights from recent meetings, with each report linking directly to relevant follow-up tasks or documents. Decisions and action items are never lost. **Milestones Widget** Chronological view of upcoming deadlines and key deliverables with status and risk indicators. Never miss a critical deadline and quickly address anything at risk. **Latest Insights Widget** Trends, blockers, team health signals, and analytics—all transparently sourced from surveys, project updates, and system data. Make proactive, data-driven decisions with real-time visibility. ## Your Always-Available Team PA On the right side of your workspace, you'll find your Team PA chat interface. This isn't just a chatbot—it's your team's dedicated assistant that understands your context, tools, and workflows. **What makes your Team PA special:** * **Context-aware**: Knows about your projects, deadlines, team members, and recent activities * **Proactive**: Surfaces important information before you ask for it * **Connected**: Integrates with all your existing tools and keeps them in sync * **Collaborative**: Can work with other team PAs across your organization ## Bringing in Sub-Assistants with @-Mentions One of Envole's most powerful features is the ability to bring specialized Sub-Assistants into any conversation using simple @-mentions. Type @ and see all available assistants in your organization. **How @-mentions work:** * Type @ to see available Sub-Assistants * Mention multiple assistants for collaborative responses * Each assistant contributes their specialized expertise * Get comprehensive solutions that combine different perspectives For example, you might @mention a Sales Research Assistant when planning a product launch, or bring in a Content Generator when creating marketing materials. ## Tool Integrations Envole connects seamlessly with the tools your team already uses. Your Team PA and Sub-Assistants can read from and write to: * **Communication**: Slack, Microsoft Teams, Gmail * **Project Management**: Jira, Linear, Asana, Monday * **Documentation**: Notion, Confluence, Google Drive * **Development**: GitHub, GitLab * **CRM**: HubSpot, Salesforce * **And many more...** The beauty is that you don't need to change how your team works—Envole enhances your existing workflows by providing intelligent assistance and automation. ## Real-Time Collaboration Your Team PA doesn't work in isolation. It can collaborate with other Team PAs across your organization, creating a connected nervous system for your company. When the Product team needs input from Engineering, or Sales needs insights from Marketing, your PAs can coordinate automatically. This cross-functional collaboration happens seamlessly in the background, ensuring information flows where it's needed without the usual friction of manual coordination. ## What's Next? Now that you've seen how Envole's dashboard and Team PA work, let's dive deeper into understanding what makes Team Personal Assistants so powerful for team productivity. Discover how Team PAs keep your entire team organized and productive ## Ready to Get Started? Start your free trial and see the difference See Envole in action with your team's use case # API Integration Source: https://docs.envole.ai/human-in-the-loop/api-integration/index Complete guide to implementing tool approval via the message API ## Overview Tool approval responses are submitted through the standard [Add Session Thread Message](/api-reference/session-thread/add-session-thread-message) endpoint. The approval decisions are included in the `content` field of the message, alongside optional text feedback. ## Request Format ### Endpoint ``` POST /api/assistants/threads/{threadId}/messages ``` ### Authentication ```typescript const headers = { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json', 'X-Envole-User-Id': USER_ID }; ``` ### Basic Approval Response ```typescript const approvalResponse = { content: [ { type: 'tool_approval_result', tool_approval_results: [ { toolId: 'tool_123', toolName: 'google_calendar_create_event', toolProvider: 'GOOGLE_CALENDAR', toolCategory: 'CALENDAR', toolExecutionId: 'exec_123', toolExecutionBatchId: 'batch_456', toolMemoryId: 'mem_789', toolArguments: { event_title: 'Project Review Meeting', start_time: '2024-01-15T14:00:00Z', end_time: '2024-01-15T15:00:00Z', attendees: 'john@company.com,mary@company.com', location: 'Conference Room A' }, approvalResult: 'ABORTED_WITH_FEEDBACK' } ] } ] }; await fetch(`${API_BASE_URL}/api/assistants/threads/${threadId}/messages`, { method: 'POST', headers, body: JSON.stringify(approvalResponse) }); ``` ## Approval Result Structure Each tool approval result must include all fields from the original approval request: ```typescript interface ToolApprovalResult { toolId: string; // From original request toolName: string; // From original request toolProvider: string; // From original request toolCategory: string; // From original request toolExecutionId: string; // From original request toolExecutionBatchId: string; // From original request toolMemoryId: string; // From original request toolArguments: object; // From original request approvalResult: 'ABORTED_WITH_FEEDBACK' | 'DENIED' | 'ABORTED'; } ``` **Important**: You must preserve all original fields from the `TOOL_EXECUTION_APPROVAL_REQUEST` event and only modify the `approvalResult` field. ## Batch Response Examples ### Mixed Approval/Denial ```typescript const mixedBatchResponse = { content: [ { type: 'tool_approval_result', tool_approval_results: [ { toolId: 'tool_123', toolName: 'send_email', toolProvider: 'GMAIL', toolCategory: 'EMAIL', toolExecutionId: 'exec_123', toolExecutionBatchId: 'batch_456', toolMemoryId: 'mem_789', toolArguments: { to: 'user@company.com', subject: 'Project Update', body: 'Progress report attached' }, approvalResult: 'ABORTED_WITH_FEEDBACK' }, { toolId: 'tool_124', toolName: 'schedule_meeting', toolProvider: 'GOOGLE_CALENDAR', toolCategory: 'CALENDAR', toolExecutionId: 'exec_124', toolExecutionBatchId: 'batch_456', toolMemoryId: 'mem_790', toolArguments: { title: 'Follow-up Meeting', date: '2024-01-16T10:00:00Z' }, approvalResult: 'DENIED' } ] } ] }; ``` ### Abort with Feedback ```typescript const abortWithFeedback = { content: [ { type: 'text', text: 'The email recipient list includes external contacts that should not receive this confidential information. Please revise the distribution list.' }, { type: 'tool_approval_result', tool_approval_results: [ { toolId: 'tool_123', toolName: 'send_email', toolProvider: 'GMAIL', toolCategory: 'EMAIL', toolExecutionId: 'exec_123', toolExecutionBatchId: 'batch_456', toolMemoryId: 'mem_789', toolArguments: { to: 'external@competitor.com,internal@company.com', subject: 'Confidential Project Update', body: 'Internal strategy document attached' }, approvalResult: 'ABORTED' }, { toolId: 'tool_124', toolName: 'save_draft', toolProvider: 'GMAIL', toolCategory: 'EMAIL', toolExecutionId: 'exec_124', toolExecutionBatchId: 'batch_456', toolMemoryId: 'mem_790', toolArguments: { subject: 'Confidential Project Update', body: 'Internal strategy document attached' }, approvalResult: 'ABORTED' } ] } ] }; ``` ## File and Image Restrictions ### Allowed: Files with Abort Responses ```typescript const abortWithScreenshot = { content: [ { type: 'text', text: 'The calendar event has the wrong timezone. See screenshot of the correct settings:' }, { type: 'image', image_url: { url: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...' } }, { type: 'tool_approval_result', tool_approval_results: [ { toolExecutionId: 'exec_123', toolExecutionBatchId: 'batch_456', // ... other required fields approvalResult: 'ABORTED' } ] } ] }; ``` ### Not Allowed: Files with Approval/Denial ```typescript // ❌ Files will be ignored for non-abort responses const approvalWithFile = { content: [ { type: 'image', image_url: { url: 'reference.png' } // Will be ignored }, { type: 'tool_approval_result', tool_approval_results: [ { toolExecutionId: 'exec_123', approvalResult: 'ABORTED_WITH_FEEDBACK' // Files ignored for approved/denied tools } ] } ] }; ``` ## Complete Implementation Example ```typescript class ToolApprovalHandler { private pendingApprovals = new Map(); handleApprovalRequest(requests: ToolApprovalRequest[]) { // Group by batch ID const batchId = requests[0].toolExecutionBatchId; this.pendingApprovals.set(batchId, requests); // Show approval UI this.showApprovalInterface(requests); } async submitApprovalBatch( batchId: string, decisions: Map, feedback?: string ) { const requests = this.pendingApprovals.get(batchId); if (!requests) { throw new Error(`No pending approvals for batch ${batchId}`); } // Build approval results const toolApprovalResults = requests.map(request => ({ toolId: request.toolId, toolName: request.toolName, toolProvider: request.toolProvider, toolCategory: request.toolCategory, toolExecutionId: request.toolExecutionId, toolExecutionBatchId: request.toolExecutionBatchId, toolMemoryId: request.toolMemoryId, toolArguments: request.toolArguments, approvalResult: decisions.get(request.toolExecutionId) })); // Build content array const content = []; // Add feedback text if provided if (feedback) { content.push({ type: 'text', text: feedback }); } // Add approval results content.push({ type: 'tool_approval_result', tool_approval_results: toolApprovalResults }); // Submit to API const response = await fetch( `${API_BASE_URL}/api/assistants/threads/${this.threadId}/messages`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', 'X-Envole-User-Id': this.userId }, body: JSON.stringify({ content }) } ); if (!response.ok) { const error = await response.json(); throw new Error(`Approval submission failed: ${error.message}`); } // Clean up this.pendingApprovals.delete(batchId); } // Helper method for individual tool decisions setToolDecision(toolExecutionId: string, decision: ApprovalDecision) { // Find batch containing this tool let batchId: string | undefined; let batchRequests: ToolApprovalRequest[] | undefined; for (const [id, requests] of this.pendingApprovals.entries()) { if (requests.some(req => req.toolExecutionId === toolExecutionId)) { batchId = id; batchRequests = requests; break; } } if (!batchId || !batchRequests) { throw new Error(`Tool ${toolExecutionId} not found in pending approvals`); } // Update UI state this.updateToolDecision(toolExecutionId, decision); // Check if batch is complete const allDecisions = this.getAllBatchDecisions(batchId); if (allDecisions.size === batchRequests.length) { // All tools decided - ready to submit this.enableBatchSubmission(batchId); } } } ``` ## Response Handling The API responds with standard SSE events. After submitting approvals, you'll receive: 1. `NOTIFICATION_TOOL_EXECUTION_APPROVAL_ACCEPTED` for approved tools 2. `NOTIFICATION_TOOL_EXECUTION_APPROVAL_DENIED` for denied tools 3. `NOTIFICATION_TOOL_EXECUTION_APPROVAL_ABORTED` for aborted tools 4. Standard `AGENT_RESPONSE_*` events as the agent continues processing ## Error Responses ### Validation Errors ```json { "error": "Invalid tool approval batch", "details": { "batchId": "batch_456", "issues": [ { "toolExecutionId": "exec_123", "error": "Missing required field: toolArguments" }, { "toolExecutionId": "exec_124", "error": "Invalid approvalResult: must be ABORTED_WITH_FEEDBACK, DENIED, or ABORTED" } ] } } ``` ### State Constraint Violations ```json { "error": "Invalid approval batch: cannot mix ABORTED with other approval states", "batchId": "batch_456", "conflictingStates": ["ABORTED_WITH_FEEDBACK", "ABORTED"] } ``` ## Next Steps * Review [Best Practices](/human-in-the-loop/best-practices/index) for UX recommendations * See [Implementation Examples](/human-in-the-loop/examples/index) for complete code samples * Learn about [Error Handling](/human-in-the-loop/error-handling/index) strategies # Approval States Source: https://docs.envole.ai/human-in-the-loop/approval-states/index Understanding approval decisions and their constraints ## Available Approval States The system supports three approval decisions for each tool execution: * **APPROVED**: Tool will execute with provided arguments * **DENIED**: Tool execution will be skipped * **ABORTED\_WITH\_FEEDBACK\_WITH\_FEEDBACK**: Tool execution cancelled with user feedback ## State Combination Rules ### Mixed States (Allowed) Within a single batch, you can mix APPROVED and DENIED states: ```typescript // ✅ VALID: Mix of approvals and denials const validBatchResponse = [ { toolExecutionId: 'exec_123', toolExecutionBatchId: 'batch_456', approvalResult: 'APPROVED' }, { toolExecutionId: 'exec_124', toolExecutionBatchId: 'batch_456', approvalResult: 'DENIED' }, { toolExecutionId: 'exec_125', toolExecutionBatchId: 'batch_456', approvalResult: 'APPROVED' } ]; ``` ### Abort Restrictions (System Limitation) **Critical Constraint**: If any tool in a batch has an ABORTED\_WITH\_FEEDBACK state, ALL tools in that batch must be ABORTED\_WITH\_FEEDBACK. You cannot mix ABORTED\_WITH\_FEEDBACK with APPROVED or DENIED states. ```typescript // ✅ VALID: All tools aborted const validAbortResponse = [ { toolExecutionId: 'exec_123', toolExecutionBatchId: 'batch_456', approvalResult: 'ABORTED_WITH_FEEDBACK' }, { toolExecutionId: 'exec_124', toolExecutionBatchId: 'batch_456', approvalResult: 'ABORTED_WITH_FEEDBACK' } ]; // ❌ INVALID: Mixed abort with other states - will return error const invalidMixedResponse = [ { toolExecutionId: 'exec_123', toolExecutionBatchId: 'batch_456', approvalResult: 'APPROVED' // Error: cannot mix with abort }, { toolExecutionId: 'exec_124', toolExecutionBatchId: 'batch_456', approvalResult: 'ABORTED_WITH_FEEDBACK' } ]; ``` ## When to Use Each State ### APPROVED Use when the tool execution should proceed as planned: * Tool arguments look correct * User authorizes the action * No concerns about the operation **Example**: User reviews calendar event creation and confirms the meeting details are accurate. ### DENIED Use when the tool should not execute but the overall workflow can continue: * Tool arguments are incorrect but fixable * User doesn't want this specific action * Timing isn't right for this operation **Example**: User denies sending an email because the recipient list needs revision, but approves creating a draft. ### ABORTED\_WITH\_FEEDBACK Use when there are fundamental issues requiring workflow termination: * Tool arguments indicate a serious problem * User wants to stop the entire process * Additional context/feedback is needed **Example**: User sees the agent is about to delete important data and wants to abort the entire operation with feedback about what went wrong. ## Abort vs Deny Decision Matrix | Scenario | Recommended State | Reason | | ----------------------------------- | ----------------------- | ------------------------------------------ | | Wrong recipient in email | DENIED | Specific tool issue, workflow can continue | | Incorrect calendar time | DENIED | Specific parameter problem | | Agent misunderstood entire request | ABORTED\_WITH\_FEEDBACK | Fundamental workflow issue | | About to perform destructive action | ABORTED\_WITH\_FEEDBACK | Safety concern requiring full stop | | User wants to provide feedback | ABORTED\_WITH\_FEEDBACK | Need to communicate back to agent | ## UX Recommendations for State Handling ### Button vs Text Input Patterns Based on system constraints and UX best practices: **For APPROVED/DENIED**: Use individual buttons per tool ```typescript // Safe to handle individually since they can be mixed function handleApprove(toolExecutionId: string) { setBatchDecision(toolExecutionId, 'APPROVED'); } function handleDeny(toolExecutionId: string) { setBatchDecision(toolExecutionId, 'DENIED'); } ``` **For ABORTED\_WITH\_FEEDBACK**: Use text input for feedback ```typescript // When user types feedback, abort entire batch function handleFeedbackSubmit(feedback: string, batchId: string) { // Abort ALL tools in batch with user feedback const allToolsAborted = batchTools.map(tool => ({ toolExecutionId: tool.toolExecutionId, toolExecutionBatchId: batchId, approvalResult: 'ABORTED_WITH_FEEDBACK' })); submitBatchResponse(allToolsAborted, feedback); } ``` ### State Validation Implement client-side validation to prevent invalid state combinations: ```typescript function validateBatchStates(decisions: Map): ValidationResult { const states = Array.from(decisions.values()); const hasAbort = states.includes('ABORTED_WITH_FEEDBACK'); const hasOtherStates = states.some(state => state !== 'ABORTED_WITH_FEEDBACK'); if (hasAbort && hasOtherStates) { return { valid: false, error: 'Cannot mix ABORTED_WITH_FEEDBACK with APPROVED or DENIED states' }; } return { valid: true }; } function onSubmitBatch(batchId: string) { const decisions = getBatchDecisions(batchId); const validation = validateBatchStates(decisions); if (!validation.valid) { showError(validation.error); return; } submitBatch(batchId, decisions); } ``` ### Progressive State Selection Guide users away from problematic state combinations: ```typescript function handleStateChange(toolId: string, newState: ApprovalState) { const currentBatch = getBatchForTool(toolId); if (newState === 'ABORTED_WITH_FEEDBACK') { // Warn user about batch-wide impact showWarning('Aborting will cancel all tools in this batch. Continue?'); // Auto-abort other tools in batch currentBatch.tools.forEach(tool => { if (tool.toolExecutionId !== toolId) { setBatchDecision(tool.toolExecutionId, 'ABORTED_WITH_FEEDBACK'); } }); } setBatchDecision(toolId, newState); } ``` ## Error Scenarios ### Mixed Abort Error Response When you attempt to submit invalid mixed states: ```json { "error": "Invalid approval batch: cannot mix ABORTED_WITH_FEEDBACK with other approval states", "batchId": "batch_456", "invalidStates": [ { "toolExecutionId": "exec_123", "state": "APPROVED" }, { "toolExecutionId": "exec_124", "state": "ABORTED_WITH_FEEDBACK" } ] } ``` Handle this error by enforcing consistent batch states: ```typescript function handleBatchError(error: BatchError) { if (error.type === 'mixed_abort_states') { // Force user to choose: abort all or none showStateConflictDialog(error.batchId, error.invalidStates); } } ``` ## Content Field Considerations Tool approval responses that are **not** abortions cannot include files or images in the content field - these will be ignored by the system. ```typescript // ✅ VALID: Abort with file attachment const abortWithFile = { content: [ { type: 'tool_approval_result', tool_approval_results: [/* aborted tools */] }, { type: 'image', image_url: { url: 'screenshot_of_issue.png' } // Allowed for aborts } ] }; // ❌ INVALID: Approval/denial with file (file will be ignored) const approvalWithFile = { content: [ { type: 'tool_approval_result', tool_approval_results: [/* approved tools */] }, { type: 'image', image_url: { url: 'reference.png' } // Will be ignored } ] }; ``` ## Next Steps * Learn about [API Integration](/human-in-the-loop/api-integration/index) for proper request formatting * Review [Best Practices](/human-in-the-loop/best-practices/index) for UX patterns * See [Error Handling](/human-in-the-loop/error-handling/index) for managing validation failures # Batch Management Source: https://docs.envole.ai/human-in-the-loop/batch-management/index Critical concepts for handling grouped tool approvals ## Why Batch Management Matters **Critical System Requirement**: All tool approvals within the same `toolExecutionBatchId` must be responded to simultaneously in a single API call. Individual responses will cause the batch to complete prematurely, potentially leaving some tools unprocessed. This is a fundamental constraint of the approval system that directly impacts both backend processing and user experience design. ## Understanding Tool Execution Batches ### Batch Identification Every tool requiring approval includes a `toolExecutionBatchId` field that groups related tool executions: ```json { "toolExecutionApprovalRequest": [ { "toolExecutionId": "exec_123", "toolExecutionBatchId": "batch_456", "toolName": "send_email", // ... other fields }, { "toolExecutionId": "exec_124", "toolExecutionBatchId": "batch_456", "toolName": "create_calendar_event", // ... other fields } ] } ``` Both tools share `batch_456`, meaning they must be approved or denied together. ### Why Batches Exist Batches ensure atomic operations and maintain workflow integrity: * **Atomic Operations**: Related tools succeed or fail together * **Workflow Consistency**: Prevents partial execution of multi-step processes * **User Context**: Groups logically related actions for easier decision-making ## Batch Response Requirements ### Single Response Rule The backend expects exactly one response containing decisions for all tools in a batch: ```typescript // ✅ CORRECT: Single response with all approvals const batchResponse = { content: [ { type: 'tool_approval_result', tool_approval_results: [ { toolExecutionId: 'exec_123', toolExecutionBatchId: 'batch_456', approvalResult: 'APPROVED' }, { toolExecutionId: 'exec_124', toolExecutionBatchId: 'batch_456', approvalResult: 'DENIED' } ] } ] }; // ❌ INCORRECT: Separate responses // This will cause premature batch completion await approveIndividualTool('exec_123', 'APPROVED'); await approveIndividualTool('exec_124', 'DENIED'); ``` ### Incomplete Batch Consequences When a batch receives partial responses: 1. **Premature Completion**: The agent may respond before all tools are processed 2. **Undefined State**: Unresponded tools may be left in pending state 3. **Workflow Failure**: Multi-step processes may fail due to missing tool results ## UX Implications ### Batch Processing Patterns **Recommended**: Collect all decisions before submitting ```typescript // Collect user decisions for entire batch const batchDecisions = new Map(); const batchId = 'batch_456'; // User makes decisions through UI batchDecisions.set('exec_123', 'APPROVED'); batchDecisions.set('exec_124', 'DENIED'); // Submit all decisions at once when batch is complete if (batchDecisions.size === totalToolsInBatch) { submitBatchResponse(batchId, batchDecisions); } ``` **Avoid**: Immediate individual processing ```typescript // ❌ This pattern causes batch completion issues function onApproveButtonClick(toolExecutionId) { // Don't immediately submit individual approvals submitApproval(toolExecutionId, 'APPROVED'); // WRONG } ``` ### UI Design Patterns **Batch-Aware Interface**: * Group tools by `toolExecutionBatchId` in the UI * Show batch completion progress (e.g., "2 of 3 tools decided") * Disable submission until all tools in batch are decided * Provide batch-level actions ("Approve All", "Deny All") **Example Batch UI State**: ```typescript interface BatchState { batchId: string; tools: ToolApprovalRequest[]; decisions: Map; isComplete: boolean; canSubmit: boolean; } const batchState = { batchId: 'batch_456', tools: [tool1, tool2, tool3], decisions: new Map([ ['exec_123', 'APPROVED'], ['exec_124', 'PENDING'], // Still waiting ['exec_125', 'DENIED'] ]), isComplete: false, canSubmit: false }; ``` ## Implementation Strategies ### Batch Collection Pattern ```typescript class ApprovalBatchManager { private batches = new Map(); addApprovalRequest(request: ToolApprovalRequest) { const batchId = request.toolExecutionBatchId; if (!this.batches.has(batchId)) { this.batches.set(batchId, { batchId, tools: [], decisions: new Map(), isComplete: false }); } const batch = this.batches.get(batchId)!; batch.tools.push(request); } setDecision(toolExecutionId: string, decision: ApprovalDecision) { for (const batch of this.batches.values()) { if (batch.tools.find(t => t.toolExecutionId === toolExecutionId)) { batch.decisions.set(toolExecutionId, decision); // Check if batch is complete if (batch.decisions.size === batch.tools.length) { batch.isComplete = true; this.submitBatch(batch); } break; } } } private submitBatch(batch: BatchState) { const approvalResults = Array.from(batch.decisions.entries()).map( ([toolExecutionId, decision]) => ({ toolExecutionId, toolExecutionBatchId: batch.batchId, approvalResult: decision }) ); // Submit all approvals in single API call submitApprovalResponse(approvalResults); } } ``` ## Common Pitfalls 1. **Immediate Processing**: Don't submit approvals as soon as user clicks buttons 2. **Ignoring Batch ID**: Always group tools by `toolExecutionBatchId` 3. **Partial Submissions**: Never submit incomplete batches 4. **State Management**: Don't lose track of pending decisions across UI updates ## Next Steps * Learn about [Approval States](/human-in-the-loop/approval-states/index) and their constraints * Review [API Integration](/human-in-the-loop/api-integration/index) for proper request formatting * See [Best Practices](/human-in-the-loop/best-practices/index) for UX recommendations # Best Practices Source: https://docs.envole.ai/human-in-the-loop/best-practices/index UX patterns and implementation strategies based on production experience ## UX Design Patterns ### Batch-Aware Interface Design **Group tools by batch**: Always visually group tools that share the same `toolExecutionBatchId` to help users understand they need to be decided together. ```typescript interface BatchGroup { batchId: string; tools: ToolApprovalRequest[]; title: string; description?: string; } function ApprovalBatchCard({ batch }: { batch: BatchGroup }) { return (

{batch.title}

{batch.tools.length} tools • Must be decided together
{batch.tools.map(tool => ( ))}
); } ``` ### Progress Indicators Show completion status to guide users toward full batch decisions: ```typescript function BatchProgress({ batchId, totalTools, decidedTools }: BatchProgressProps) { const isComplete = decidedTools === totalTools; const percentage = (decidedTools / totalTools) * 100; return (
{decidedTools} of {totalTools} tools decided {isComplete && ' • Ready to submit'}
); } ``` ### Approval Action Patterns **Individual Tool Actions**: For APPROVED and DENIED states ```typescript function ToolActions({ tool, onDecision }: ToolActionsProps) { return (
); } ``` **Batch-Level Actions**: For convenience and abort scenarios ```typescript function BatchActions({ batchId, tools }: BatchActionsProps) { const [showFeedbackInput, setShowFeedbackInput] = useState(false); return (
{/* Quick actions for approve/deny all */} {/* Feedback input for abort */} {showFeedbackInput ? ( abortBatchWithFeedback(batchId, tools, feedback)} onCancel={() => setShowFeedbackInput(false)} /> ) : ( )}
); } ``` ## State Management Strategies ### Centralized Batch Manager ```typescript class ApprovalStateManager { private batches = new Map(); private listeners = new Set(); addApprovalRequest(request: ToolApprovalRequest) { const batchId = request.toolExecutionBatchId; if (!this.batches.has(batchId)) { this.batches.set(batchId, { batchId, tools: [], decisions: new Map(), isComplete: false, canSubmit: false, submittedAt: null }); } this.batches.get(batchId)!.tools.push(request); this.notifyListeners(); } setDecision(toolExecutionId: string, decision: ApprovalDecision) { for (const batch of this.batches.values()) { const tool = batch.tools.find(t => t.toolExecutionId === toolExecutionId); if (tool) { batch.decisions.set(toolExecutionId, decision); this.updateBatchState(batch); this.notifyListeners(); break; } } } private updateBatchState(batch: BatchState) { const totalTools = batch.tools.length; const decidedTools = batch.decisions.size; batch.isComplete = decidedTools === totalTools; batch.canSubmit = batch.isComplete && this.validateBatchDecisions(batch); } private validateBatchDecisions(batch: BatchState): boolean { const decisions = Array.from(batch.decisions.values()); const hasAbort = decisions.includes('ABORTED'); const hasOtherStates = decisions.some(d => d !== 'ABORTED'); // Invalid: mixed abort with other states if (hasAbort && hasOtherStates) { return false; } return true; } async submitBatch(batchId: string, feedback?: string) { const batch = this.batches.get(batchId); if (!batch || !batch.canSubmit) { throw new Error(`Batch ${batchId} is not ready for submission`); } try { await this.apiSubmitter.submitBatch(batch, feedback); batch.submittedAt = new Date(); this.notifyListeners(); } catch (error) { console.error('Batch submission failed:', error); throw error; } } } ``` ### React Hook Integration ```typescript function useApprovalBatch(batchId: string) { const [batch, setBatch] = useState(null); useEffect(() => { const listener = (updatedBatch: BatchState) => { if (updatedBatch.batchId === batchId) { setBatch({ ...updatedBatch }); } }; ApprovalStateManager.addListener(listener); setBatch(ApprovalStateManager.getBatch(batchId)); return () => ApprovalStateManager.removeListener(listener); }, [batchId]); const setDecision = useCallback((toolId: string, decision: ApprovalDecision) => { ApprovalStateManager.setDecision(toolId, decision); }, []); const submitBatch = useCallback((feedback?: string) => { return ApprovalStateManager.submitBatch(batchId, feedback); }, [batchId]); return { batch, setDecision, submitBatch }; } ``` ## Feedback Collection Patterns ### Contextual Feedback Input ```typescript function FeedbackInput({ tool, onSubmit, placeholder = "Why are you stopping this action?" }: FeedbackInputProps) { const [feedback, setFeedback] = useState(''); const [isSubmitting, setIsSubmitting] = useState(false); const handleSubmit = async () => { if (!feedback.trim()) { toast.error('Please provide feedback before aborting'); return; } setIsSubmitting(true); try { await onSubmit(feedback); } catch (error) { toast.error('Failed to submit feedback'); } finally { setIsSubmitting(false); } }; return (

Stopping: {tool.toolName}

This will abort all tools in the current batch.