Files
2026-07-13 12:43:34 +08:00

365 lines
17 KiB
Python

from fastapi import APIRouter
from fastapi import HTTPException, Depends ,Security
from fastapi_sqlalchemy import db
from pydantic import BaseModel
from superagi.worker import execute_agent
from superagi.helper.auth import validate_api_key,get_organisation_from_api_key
from superagi.models.agent import Agent
from superagi.models.agent_execution_config import AgentExecutionConfiguration
from superagi.models.agent_config import AgentConfiguration
from superagi.models.agent_schedule import AgentSchedule
from superagi.models.project import Project
from superagi.models.workflows.agent_workflow import AgentWorkflow
from superagi.models.agent_execution import AgentExecution
from superagi.models.organisation import Organisation
from superagi.models.knowledges import Knowledges
from superagi.models.resource import Resource
from superagi.controllers.types.agent_with_config import AgentConfigExtInput,AgentConfigUpdateExtInput
from superagi.models.workflows.iteration_workflow import IterationWorkflow
from superagi.helper.s3_helper import S3Helper
from datetime import datetime
from typing import Optional,List
from superagi.models.toolkit import Toolkit
from superagi.apm.event_handler import EventHandler
from superagi.config.config import get_config
router = APIRouter()
class AgentExecutionIn(BaseModel):
name: Optional[str]
goal: Optional[List[str]]
instruction: Optional[List[str]]
class Config:
orm_mode = True
class RunFilterConfigIn(BaseModel):
run_ids:Optional[List[int]]
run_status_filter:Optional[str]
class Config:
orm_mode = True
class ExecutionStateChangeConfigIn(BaseModel):
run_ids:Optional[List[int]]
class Config:
orm_mode = True
class RunIDConfig(BaseModel):
run_ids:List[int]
class Config:
orm_mode = True
@router.post("", status_code=200)
def create_agent_with_config(agent_with_config: AgentConfigExtInput,
api_key: str = Security(validate_api_key), organisation:Organisation = Depends(get_organisation_from_api_key)):
project=Project.find_by_org_id(db.session, organisation.id)
try:
tools_arr=Toolkit.get_tool_and_toolkit_arr(db.session,organisation.id,agent_with_config.tools)
except Exception as e:
raise HTTPException(status_code=404, detail=str(e))
agent_with_config.tools=tools_arr
agent_with_config.project_id=project.id
agent_with_config.exit="No exit criterion"
agent_with_config.permission_type="God Mode"
agent_with_config.LTM_DB=None
db_agent = Agent.create_agent_with_config(db, agent_with_config)
if agent_with_config.schedule is not None:
agent_schedule = AgentSchedule.save_schedule_from_config(db.session, db_agent, agent_with_config.schedule)
if agent_schedule is None:
raise HTTPException(status_code=500, detail="Failed to schedule agent")
EventHandler(session=db.session).create_event('agent_created', {'agent_name': agent_with_config.name,
'model': agent_with_config.model}, db_agent.id,
organisation.id if organisation else 0)
db.session.commit()
return {
"agent_id": db_agent.id
}
start_step = AgentWorkflow.fetch_trigger_step_id(db.session, db_agent.agent_workflow_id)
iteration_step_id = IterationWorkflow.fetch_trigger_step_id(db.session,
start_step.action_reference_id).id if start_step.action_type == "ITERATION_WORKFLOW" else -1
# Creating an execution with RUNNING status
execution = AgentExecution(status='CREATED', last_execution_time=datetime.now(), agent_id=db_agent.id,
name="New Run", current_agent_step_id=start_step.id, iteration_workflow_step_id=iteration_step_id)
agent_execution_configs = {
"goal": agent_with_config.goal,
"instruction": agent_with_config.instruction,
"constraints": agent_with_config.constraints,
"exit": agent_with_config.exit,
"tools": agent_with_config.tools,
"iteration_interval": agent_with_config.iteration_interval,
"model": agent_with_config.model,
"permission_type": agent_with_config.permission_type,
"LTM_DB": agent_with_config.LTM_DB,
"max_iterations": agent_with_config.max_iterations,
"user_timezone": agent_with_config.user_timezone,
"knowledge": agent_with_config.knowledge
}
db.session.add(execution)
db.session.commit()
db.session.flush()
AgentExecutionConfiguration.add_or_update_agent_execution_config(session=db.session, execution=execution,
agent_execution_configs=agent_execution_configs)
organisation = db_agent.get_agent_organisation(db.session)
EventHandler(session=db.session).create_event('agent_created', {'agent_name': agent_with_config.name,
'model': agent_with_config.model}, db_agent.id,
organisation.id if organisation else 0)
# execute_agent.delay(execution.id, datetime.now())
db.session.commit()
return {
"agent_id": db_agent.id
}
@router.post("/{agent_id}/run",status_code=200)
def create_run(agent_id:int,agent_execution: AgentExecutionIn,api_key: str = Security(validate_api_key),organisation:Organisation = Depends(get_organisation_from_api_key)):
agent=Agent.get_agent_from_id(db.session,agent_id)
if not agent:
raise HTTPException(status_code=404, detail="Agent not found")
project=Project.find_by_id(db.session, agent.project_id)
if project.organisation_id!=organisation.id:
raise HTTPException(status_code=404, detail="Agent not found")
db_schedule=AgentSchedule.find_by_agent_id(db.session, agent_id)
if db_schedule is not None:
raise HTTPException(status_code=409, detail="Agent is already scheduled,cannot run")
start_step = AgentWorkflow.fetch_trigger_step_id(db.session, agent.agent_workflow_id)
db_agent_execution=AgentExecution.get_execution_by_agent_id_and_status(db.session, agent_id, "CREATED")
if db_agent_execution is None:
db_agent_execution = AgentExecution(status="RUNNING", last_execution_time=datetime.now(),
agent_id=agent_id, name=agent_execution.name, num_of_calls=0,
num_of_tokens=0,
current_agent_step_id=start_step.id)
db.session.add(db_agent_execution)
else:
db_agent_execution.status = "RUNNING"
db.session.commit()
db.session.flush()
agent_execution_configs = {}
if agent_execution.goal is not None:
agent_execution_configs = {
"goal": agent_execution.goal,
}
if agent_execution.instruction is not None:
agent_execution_configs["instructions"] = agent_execution.instruction,
if agent_execution_configs != {}:
AgentExecutionConfiguration.add_or_update_agent_execution_config(session=db.session, execution=db_agent_execution,
agent_execution_configs=agent_execution_configs)
EventHandler(session=db.session).create_event('run_created',
{'agent_execution_id': db_agent_execution.id,
'agent_execution_name':db_agent_execution.name
},
agent_id,
organisation.id if organisation else 0)
agent_execution_knowledge = AgentConfiguration.get_agent_config_by_key_and_agent_id(session= db.session, key= 'knowledge', agent_id= agent_id)
if agent_execution_knowledge and agent_execution_knowledge.value != 'None':
knowledge_name = Knowledges.get_knowledge_from_id(db.session, int(agent_execution_knowledge.value)).name
if knowledge_name is not None:
EventHandler(session=db.session).create_event('knowledge_picked',
{'knowledge_name': knowledge_name,
'agent_execution_id': db_agent_execution.id},
agent_id,
organisation.id if organisation else 0
)
if db_agent_execution.status == "RUNNING":
execute_agent.delay(db_agent_execution.id, datetime.now())
return {
"run_id":db_agent_execution.id
}
@router.put("/{agent_id}",status_code=200)
def update_agent(agent_id: int, agent_with_config: AgentConfigUpdateExtInput,api_key: str = Security(validate_api_key),
organisation:Organisation = Depends(get_organisation_from_api_key)):
db_agent= Agent.get_active_agent_by_id(db.session, agent_id)
if not db_agent:
raise HTTPException(status_code=404, detail="agent not found")
project=Project.find_by_id(db.session, db_agent.project_id)
if project is None:
raise HTTPException(status_code=404, detail="Project not found")
if project.organisation_id!=organisation.id:
raise HTTPException(status_code=404, detail="Agent not found")
# db_execution=AgentExecution.get_execution_by_agent_id_and_status(db.session, agent_id, "RUNNING")
# if db_execution is not None:
# raise HTTPException(status_code=409, detail="Agent is already running,please pause and then update")
db_schedule=AgentSchedule.find_by_agent_id(db.session, agent_id)
if db_schedule is not None:
raise HTTPException(status_code=409, detail="Agent is already scheduled,cannot update")
try:
tools_arr=Toolkit.get_tool_and_toolkit_arr(db.session,organisation.id,agent_with_config.tools)
except Exception as e:
raise HTTPException(status_code=404,detail=str(e))
if agent_with_config.schedule is not None:
raise HTTPException(status_code=400,detail="Cannot schedule an existing agent")
agent_with_config.tools=tools_arr
agent_with_config.project_id=project.id
agent_with_config.exit="No exit criterion"
agent_with_config.permission_type="God Mode"
agent_with_config.LTM_DB=None
for key,value in agent_with_config.dict().items():
if hasattr(db_agent,key) and value is not None:
setattr(db_agent,key,value)
db.session.commit()
db.session.flush()
start_step = AgentWorkflow.fetch_trigger_step_id(db.session, db_agent.agent_workflow_id)
iteration_step_id = IterationWorkflow.fetch_trigger_step_id(db.session,
start_step.action_reference_id).id if start_step.action_type == "ITERATION_WORKFLOW" else -1
execution = AgentExecution(status='CREATED', last_execution_time=datetime.now(), agent_id=db_agent.id,
name="New Run", current_agent_step_id=start_step.id, iteration_workflow_step_id=iteration_step_id)
agent_execution_configs = {
"goal": agent_with_config.goal,
"instruction": agent_with_config.instruction,
"tools":agent_with_config.tools,
"constraints": agent_with_config.constraints,
"iteration_interval": agent_with_config.iteration_interval,
"model": agent_with_config.model,
"max_iterations": agent_with_config.max_iterations,
"agent_workflow": agent_with_config.agent_workflow,
}
agent_configurations = [
AgentConfiguration(agent_id=db_agent.id, key=key, value=str(value))
for key, value in agent_execution_configs.items()
]
db.session.add_all(agent_configurations)
db.session.add(execution)
db.session.commit()
db.session.flush()
AgentExecutionConfiguration.add_or_update_agent_execution_config(session=db.session, execution=execution,
agent_execution_configs=agent_execution_configs)
db.session.commit()
return {
"agent_id":db_agent.id
}
@router.post("/{agent_id}/run-status")
def get_agent_runs(agent_id:int,filter_config:RunFilterConfigIn,api_key: str = Security(validate_api_key),organisation:Organisation = Depends(get_organisation_from_api_key)):
agent= Agent.get_active_agent_by_id(db.session, agent_id)
if not agent:
raise HTTPException(status_code=404, detail="Agent not found")
project=Project.find_by_id(db.session, agent.project_id)
if project.organisation_id!=organisation.id:
raise HTTPException(status_code=404, detail="Agent not found")
db_execution_arr=[]
if filter_config.run_status_filter is not None:
filter_config.run_status_filter=filter_config.run_status_filter.upper()
db_execution_arr=AgentExecution.get_all_executions_by_filter_config(db.session, agent.id, filter_config)
response_arr=[]
for ind_execution in db_execution_arr:
response_arr.append({"run_id":ind_execution.id, "status":ind_execution.status})
return response_arr
@router.post("/{agent_id}/pause",status_code=200)
def pause_agent_runs(agent_id:int,execution_state_change_input:ExecutionStateChangeConfigIn,api_key: str = Security(validate_api_key),organisation:Organisation = Depends(get_organisation_from_api_key)):
agent= Agent.get_active_agent_by_id(db.session, agent_id)
if not agent:
raise HTTPException(status_code=404, detail="Agent not found")
project=Project.find_by_id(db.session, agent.project_id)
if project.organisation_id!=organisation.id:
raise HTTPException(status_code=404, detail="Agent not found")
#Checking if the run_ids whose output files are requested belong to the organisation
if execution_state_change_input.run_ids is not None:
try:
AgentExecution.validate_run_ids(db.session,execution_state_change_input.run_ids,organisation.id)
except Exception as e:
raise HTTPException(status_code=404, detail="One or more run id(s) not found")
db_execution_arr=AgentExecution.get_all_executions_by_status_and_agent_id(db.session, agent.id, execution_state_change_input, "RUNNING")
if db_execution_arr is not None and execution_state_change_input.run_ids is not None \
and len(db_execution_arr) != len(execution_state_change_input.run_ids):
raise HTTPException(status_code=404, detail="One or more run id(s) not found")
for ind_execution in db_execution_arr:
ind_execution.status="PAUSED"
db.session.commit()
db.session.flush()
return {
"result":"success"
}
@router.post("/{agent_id}/resume",status_code=200)
def resume_agent_runs(agent_id:int,execution_state_change_input:ExecutionStateChangeConfigIn,api_key: str = Security(validate_api_key),organisation:Organisation = Depends(get_organisation_from_api_key)):
agent= Agent.get_active_agent_by_id(db.session, agent_id)
if not agent:
raise HTTPException(status_code=404, detail="Agent not found")
project=Project.find_by_id(db.session, agent.project_id)
if project.organisation_id!=organisation.id:
raise HTTPException(status_code=404, detail="Agent not found")
if execution_state_change_input.run_ids is not None:
try:
AgentExecution.validate_run_ids(db.session,execution_state_change_input.run_ids,organisation.id)
except Exception as e:
raise HTTPException(status_code=404, detail="One or more run id(s) not found")
db_execution_arr=AgentExecution.get_all_executions_by_status_and_agent_id(db.session, agent.id, execution_state_change_input, "PAUSED")
if db_execution_arr is not None and execution_state_change_input.run_ids is not None\
and len(db_execution_arr) != len(execution_state_change_input.run_ids):
raise HTTPException(status_code=404, detail="One or more run id(s) not found")
for ind_execution in db_execution_arr:
ind_execution.status="RUNNING"
execute_agent.delay(ind_execution.id, datetime.now())
db.session.commit()
db.session.flush()
return {
"result":"success"
}
@router.post("/resources/output",status_code=200)
def get_run_resources(run_id_config:RunIDConfig,api_key: str = Security(validate_api_key),organisation:Organisation = Depends(get_organisation_from_api_key)):
if get_config('STORAGE_TYPE') != "S3":
raise HTTPException(status_code=400,detail="This endpoint only works when S3 is configured")
run_ids_arr=run_id_config.run_ids
if len(run_ids_arr)==0:
raise HTTPException(status_code=404,
detail=f"No execution_id found")
#Checking if the run_ids whose output files are requested belong to the organisation
try:
AgentExecution.validate_run_ids(db.session, run_ids_arr, organisation.id)
except Exception as e:
raise HTTPException(status_code=404, detail="One or more run id(s) not found")
db_resources_arr=Resource.find_by_run_ids(db.session, run_ids_arr)
try:
response_obj=S3Helper().get_download_url_of_resources(db_resources_arr)
except:
raise HTTPException(status_code=401,detail="Invalid S3 credentials")
return response_obj