-
Notifications
You must be signed in to change notification settings - Fork 46.1k
feat(platform): add Human In The Loop block with review workflow #11380
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
majdyz
wants to merge
49
commits into
dev
Choose a base branch
from
feat/human-in-the-loop-block
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+3,155
−93
Open
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit
Hold shift + click to select a range
b8cb244
feat(platform): add Human In The Loop block with review workflow
majdyz a27a445
feat(platform): Implement Human In The Loop block with comprehensive …
majdyz a82449c
fix(backend): Fix HumanInTheLoopBlock test failure due to missing gra…
majdyz 72f757b
fix(backend): Address critical security and reliability issues in Hum…
majdyz 807f6e2
fix(backend): Fix critical mock issue - block now uses real workflow …
majdyz d2597c4
feat(backend/frontend): Address critical HITL security and UX issues
majdyz 480489c
style: apply lint fixes
majdyz 96219aa
style: apply lint fixes to manager.py
majdyz a625fc0
fix(backend): optimize execution queue and fix API route conflicts
majdyz e0ef5e3
feat(frontend): Add maxLength validation to HITL review message textarea
majdyz b494f3e
fix(frontend): Include WAITING_FOR_REVIEW in active status for Activi…
majdyz 120746a
fix(backend): Improve HITL block execution status handling
majdyz 599582e
feat(backend): Use Literal type for HITL block status field
majdyz ee7edc5
refactor(backend): Move HITL database operations to data layer
majdyz 8780290
feat(backend): Add status transition validation and improve architecture
majdyz 59df230
remove init
majdyz 8cade32
refactor(backend): Improve Human In The Loop block architecture and d…
majdyz d2e630a
refactor(backend/executor): Simplify node status update using batch p…
majdyz f05d480
refactor(backend/data): Inline wrapper methods in human_review.py
majdyz 28ca485
refactor(backend): Major cleanup of human_review.py and execution.py
majdyz e33a362
cleanuo
majdyz 6f17a95
refactor(backend): Replace chaotic union type with structured Pending…
majdyz d13a5db
refactor(backend): Clean up review model with proper from_db pattern
majdyz 9998610
style(backend): Apply code formatting to review models
majdyz 5dc4a0e
refactor(backend): Restructure human review data model to eliminate c…
majdyz 6de947f
refactor(backend): Improve consistency and remove unnecessary complexity
majdyz d70d536
refactor(backend): Inline single-use functions
majdyz f8dd0c0
refactor(backend): Optimize HITL system with improved database patterns
majdyz 9ae926f
cleanuo
majdyz 38b080c
cleanuo
majdyz ea05cf4
fix(frontend): Update PendingReviewCard to match API response structure
majdyz 48add47
fix(frontend): Update components to use regenerated API types
majdyz 796c27e
refactor(platform): Improve API design and exception handling
majdyz a8fead6
fix(frontend): Fix stale closure issue in FloatingReviewsPanel
majdyz 75a98b7
Merge branch 'dev' into feat/human-in-the-loop-block
majdyz 4b0e971
fix(backend): Add critical security fixes for human review system
majdyz 5dda783
fix(backend): Add missing INCOMPLETE status transition rules
majdyz 81de4e5
feat(platform): Enhance Human-in-the-Loop execution resume functionality
majdyz d0ff313
Merge branch 'dev' of github.com:Significant-Gravitas/AutoGPT into fe…
majdyz 12145fa
Merge branch 'dev' of github.com:Significant-Gravitas/AutoGPT into fe…
majdyz f600574
feat(platform): enhance human-in-the-loop functionality with real-tim…
majdyz 55b9113
fix ci
majdyz 9f1e27a
revert(backend): revert unintended store changes from HITL implementa…
majdyz 23e93fc
feat(frontend): add Human-in-the-Loop block to beta blocks feature flag
majdyz 4ce2f45
Merge branch 'dev' into feat/human-in-the-loop-block
majdyz 39ec38f
Merge branch 'feat/human-in-the-loop-block' of github.com:Significant…
majdyz 8fa5762
feat(platform): enhance Human-in-the-Loop block with improved review UX
majdyz 3c71761
fix(frontend): remove unused reviewData prop from PendingReviewsList
majdyz 0422173
refactor(frontend): critical simplification and cleanup of HITL compo…
majdyz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
145 changes: 145 additions & 0 deletions
145
autogpt_platform/backend/backend/blocks/human_in_the_loop.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| from typing import Any | ||
|
|
||
| from prisma.models import PendingHumanReview | ||
|
|
||
| from backend.data.block import ( | ||
| Block, | ||
| BlockCategory, | ||
| BlockOutput, | ||
| BlockSchemaInput, | ||
| BlockSchemaOutput, | ||
| ) | ||
| from backend.data.model import SchemaField | ||
| from backend.util.json import SafeJson | ||
| from backend.util.type import convert | ||
|
|
||
|
|
||
| class HumanInTheLoopBlock(Block): | ||
| """ | ||
| This block pauses execution and waits for human approval or modification of the data. | ||
| When executed, it creates a pending review entry and sets the node execution status | ||
| to WAITING_FOR_REVIEW. The execution will remain paused until a human user either: | ||
| - Approves the data (with or without modifications) | ||
| - Rejects the data | ||
| This is useful for workflows that require human validation or intervention before | ||
| proceeding to the next steps. | ||
| """ | ||
|
|
||
| class Input(BlockSchemaInput): | ||
| data: Any = SchemaField(description="The data to be reviewed by a human user") | ||
| message: str = SchemaField( | ||
| description="Instructions or message for the human reviewer", | ||
| default="Please review and approve or modify the following data:", | ||
| ) | ||
| editable: bool = SchemaField( | ||
| description="Whether the human reviewer can edit the data", | ||
| default=True, | ||
| advanced=True, | ||
| ) | ||
|
|
||
| class Output(BlockSchemaOutput): | ||
| reviewed_data: Any = SchemaField( | ||
| description="The data after human review (may be modified)" | ||
| ) | ||
| status: str = SchemaField( | ||
| description="Status of the review: 'approved' or 'rejected'" | ||
| ) | ||
| review_message: str = SchemaField( | ||
| description="Any message provided by the reviewer", default="" | ||
| ) | ||
|
|
||
| def __init__(self): | ||
| super().__init__( | ||
| id="8b2a7b3c-6e9d-4a5f-8c1b-2e3f4a5b6c7d", | ||
| description="Pause execution and wait for human approval or modification of data", | ||
| categories={BlockCategory.BASIC}, | ||
| input_schema=HumanInTheLoopBlock.Input, | ||
| output_schema=HumanInTheLoopBlock.Output, | ||
| test_input={ | ||
| "data": {"name": "John Doe", "age": 30}, | ||
| "message": "Please verify this user data", | ||
| "editable": True, | ||
| }, | ||
| test_output=[ | ||
| ("reviewed_data", {"name": "John Doe", "age": 30}), | ||
| ("status", "approved"), | ||
| ("review_message", ""), | ||
| ], | ||
| ) | ||
|
|
||
| async def run( | ||
| self, | ||
| input_data: Input, | ||
| *, | ||
| user_id: str, | ||
| node_exec_id: str, | ||
| graph_exec_id: str, | ||
| graph_id: str, | ||
| graph_version: int, | ||
| **kwargs | ||
| ) -> BlockOutput: | ||
| # Check if there's already an approved review for this node execution | ||
| existing_review = await PendingHumanReview.prisma().find_unique( | ||
majdyz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| where={"nodeExecId": node_exec_id} | ||
| ) | ||
|
|
||
| if existing_review and existing_review.status == "APPROVED": | ||
| # Return the approved data (which may have been modified by the reviewer) | ||
| # The data field now contains the approved/modified data from the review | ||
| if ( | ||
| isinstance(existing_review.data, dict) | ||
| and "data" in existing_review.data | ||
| ): | ||
| # Extract the actual data from the review data structure | ||
| approved_data = existing_review.data["data"] | ||
majdyz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| else: | ||
| # Fallback to the stored data directly | ||
| approved_data = existing_review.data | ||
|
|
||
| approved_data = convert(approved_data, type(input_data.data)) | ||
| yield "reviewed_data", approved_data | ||
| yield "status", "approved" | ||
| yield "review_message", existing_review.reviewMessage or "" | ||
|
|
||
| # Clean up the review record as it's been processed | ||
| await PendingHumanReview.prisma().delete(where={"id": existing_review.id}) | ||
| return | ||
|
|
||
| elif existing_review and existing_review.status == "REJECTED": | ||
| # Return rejection status without data | ||
| yield "status", "rejected" | ||
| yield "review_message", existing_review.reviewMessage or "" | ||
|
|
||
| # Clean up the review record | ||
| await PendingHumanReview.prisma().delete(where={"id": existing_review.id}) | ||
| return | ||
|
|
||
| # No existing approved review, create a pending review | ||
| review_data = { | ||
| "data": input_data.data, | ||
| "message": input_data.message, | ||
| "editable": input_data.editable, | ||
| } | ||
|
|
||
| await PendingHumanReview.prisma().upsert( | ||
| where={"nodeExecId": node_exec_id}, | ||
| data={ | ||
| "create": { | ||
| "userId": user_id, | ||
| "nodeExecId": node_exec_id, | ||
| "graphExecId": graph_exec_id, | ||
| "graphId": graph_id, | ||
| "graphVersion": graph_version, | ||
| "data": SafeJson(review_data), | ||
| "status": "WAITING", | ||
| }, | ||
| "update": {"data": SafeJson(review_data), "status": "WAITING"}, | ||
| }, | ||
| ) | ||
majdyz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| # This will effectively pause the execution here | ||
| # The execution will be resumed when the review is approved | ||
| # The manager will detect the pending review and set the status to WAITING_FOR_REVIEW | ||
| return | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
majdyz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
Empty file.
41 changes: 41 additions & 0 deletions
41
autogpt_platform/backend/backend/server/v2/executions/review/model.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| from datetime import datetime | ||
| from typing import Any, Literal | ||
|
|
||
| from pydantic import BaseModel, Field | ||
|
|
||
|
|
||
| class PendingHumanReviewResponse(BaseModel): | ||
| """Response model for pending human review.""" | ||
|
|
||
| id: str = Field(description="Unique ID of the pending review") | ||
| user_id: str = Field(description="User ID associated with the review") | ||
| node_exec_id: str = Field(description="Node execution ID") | ||
| graph_exec_id: str = Field(description="Graph execution ID") | ||
| graph_id: str = Field(description="Graph ID") | ||
| graph_version: int = Field(description="Graph version") | ||
| data: Any = Field(description="Data waiting for review") | ||
| status: Literal["WAITING", "APPROVED", "REJECTED"] = Field( | ||
| description="Review status" | ||
| ) | ||
| review_message: str | None = Field( | ||
| description="Optional message from the reviewer", default=None | ||
| ) | ||
| created_at: datetime = Field(description="When the review was created") | ||
| updated_at: datetime | None = Field( | ||
| description="When the review was last updated", default=None | ||
| ) | ||
| reviewed_at: datetime | None = Field( | ||
| description="When the review was completed", default=None | ||
| ) | ||
|
|
||
|
|
||
| class ReviewActionRequest(BaseModel): | ||
| """Request model for reviewing data.""" | ||
|
|
||
| action: Literal["approve", "reject"] = Field(description="Action to take") | ||
| reviewed_data: Any | None = Field( | ||
| description="Modified data (only for approve action)", default=None | ||
| ) | ||
| message: str | None = Field( | ||
| description="Optional message from the reviewer", default=None | ||
| ) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.