Skip to content

Latest commit

 

History

History
158 lines (134 loc) · 13.4 KB

File metadata and controls

158 lines (134 loc) · 13.4 KB

Agentic Framework We are building a simple agentic framework for constructing software, doing research, and managing data. We have failed at this in the past due to a poorly specified description of the framework (my fault). Here I am trying to fully describe what pieces I want built and how those pieces will fit together. We are going to build this one piece at a time. Keep the code simple! Minimal frills. These can be added later. CLI I want to have a single installable driver for this framework. Using this driver, I should be able to start all the individual daemons (e.g. queue manager, slack handler, orchestrator). I should also be able to interact with individual components (worker harness, JSON validator). I will be using this CLI for all my personal testing. Try to keep the CLI simple, ideally each component should have it’s own CLI processing routines that are synthesized in one master CLI. Keep configurations manageable. I want to use validated JSON files for most configuration parameters. The CLI should have a single config.yaml for the entire framework, and the primary entries in that file should be the slack authentication and the location of the dropbox filestore.

Each user who uses the CLI should have a ~/.orchestrator_config.json in their home directory, which should hold state information for the CLI. This should be automatically created by the CLI if it doesnt exist. Initially, the primary use of this file should be to specify the username of the person calling the CLI. We need to define the users allowed to use the system. These will be captured in the file-system datastore (syncrhonized by dropbox daemon):

/home/chenry/DropBox/AgentStore/users/ .json (e.g. chenry.json)

.json is a user object validated by JSON scheme and should look like this: { “id” : “chenry” “slack_username” : “chenry”, “name” : “Christopher Henry”, “email” : “chenry@anl.gov”,
“permissions” : “admin” #Could also be user }

The user needs to inform the system of their username using a “login” command in the CLI, but this should be very simple with no password or authentication… just a specified username. This username should be stored in ~/.orchestrator_config.json.

All of these commands should be implemented: Documentation commands: help State setting commands: login, set-project, set-prd Data browsing commands: list-users, list-jobs, list-projects, list-prds, list-tasks (must have prd selected) Data viewing commands: view-user, view-job, view-project, view-prd Commands for agents: create-prd, research-code, create-tasks, implement-tasks,create-environment (this should use the venvman tool already on system to make an environment for the currently set project)

The CLI should handle these commands directly: help, login, set-project, set-prd, list-users, list-jobs, list-projects, list-prds, list-tasks, view-user, view-job, view-project, view-prd. For all commands to agents, the CLI should print a message object in the inbox. The messaging will be handled in the filesystem like so:

/home/chenry/DropBox/AgentStore/messaging/ inbox/ .json #message object sent from user through CLI or SLACK processed_inbox/ .json #messages processed by the orchestrator go here outbox/ .json #messages to be sent back to the user through slack or CLI processed_outbox/ .json #messages successfully sent to the user go here

The spec for the message json files looks like this: { “source” : “user”, #Could also be agent “project” : “ModelSEEDpy”, #What project is the message connected to “queue_time” : “2025-10-23T21:59:44Z”, #When the message was first placed in the “inbox” or “outbox” “processed_time” : “2025-10-23T21:59:44Z”, #When the message was processed by the orchestrator, slack handler, or CLI “command” : “help”, #The command being issued by the user “content” : {} #Dictionary of key value pairs to serve as arguments for the command }

The orchestrator should then process that message accordingly. The CLI should wait for a message in the outbox with the orchestrator’s response to the message. The response message in the outbox could have the same UUID name as the input message in the inbox (this is how the messages can be paired up). Once the response message appears, the CLI should present this response to the user along with the UUID. JSON Validator Util This project will have many json files that need validating. I don’t want to see 50 different file validation libraries in the code, and I certainly don’t want to see handcrafted file validators. We will create a JSON scheme for every file, and we will create a single JSON validation utility that will be used by all subsystems in the code to validate any needed JSON files. I expect this utility to be a very narrow wrap of the JSON scheme library which will also know where the JSON scheme files are and will offer a function to validate JSON objects when given the object type (e.g. job) and the object data. Schemes will be stored in the AgentStore:

/home/chenry/DropBox/AgentStore/JSONValidation/ Schemes/ job.scheme.json errors.out #Append validation errors with timestamps here so I have a single place to go to see what errors we are having Queue Manager: The Queue Manager’s mission is to monitor all running jobs assigned to it, check for crashed jobs, check for finished jobs, and queue up new jobs when capacity is available. The queue manager CLI should allow me to queue up a job, access the queue status, and add a new queue to the system. The directories for the Queue Manager look like this:

/home/chenry/DropBox/AgentStore/Queues// queue.json log.out Jobs/ queud_jobs/ .json running_jobs/ .json finished_jobs/ .json failed_jobs/ .json

As stated, there will be multiple queues, and these queues will be specified with JSON validated queue.json files stored in the /home/chenry/DropBox/AgentStore/Queues// directory as shown above. Here’s an example queue.json file:

Queue { “id” : “poplar”, #Config - Name used for in the filesystem and used to reference the queue in the CLI “worker_count” : 10, #Config - Number of simultaneous workers you can run “claude_cli_path” : “claude”, #Config - command line to run claude “rest_interval” : 60, #Config - How long to sleep between loops to check for queued jobs “process_id” : 12456, #Runtime - Process ID of the running queue manager “active_jobs” : 8, #Runtime - number of active jobs right now “last_update” : “2025-10-23T21:59:44Z”,#Runtime - timestamp when loop last ran “queued_jobs” : 10, #Runtime - how many jobs are queued right now

}

As can be seen, the queue.json file doesn’t just have configuration parameters like worker_count, it also has runtime parameters that will be set dynamically at runtime and updated everytime the loop runs (e.g. the json file will be resaved with updated data every time the loop runs).

Jobs will also be specified with a validated JSON file. We will create a JSON scheme for this file so this file may be easily validated. As with the queue.json, job files contain a mix of config parameters and parameters that will be dynamically updated by the job itself when it runs. To avoid race conditions, there should be a handoff in control of the job.json file from the orchestrator, which creates the job, to the queue manager, which sets the start_time, status, and process ID when the job is started (and sets the error if an error occurs at this stage), to the work harness, which sets the status, finish_time, error, and output as the job runs.

{ “project”: “ModelSEEDpy”, #Config - Name of project the job is associated with “working_directory”: “/home/chenry/projects/ClaudeProjects/ModelSEEDpy/” #Config - Where the job runs - usually the directory where the project is located, but not always “queue_time”: “2025-10-23T21:59:44Z”, #Config - when the job was queued “start_time”: “2025-10-23T21:59:44Z”, #Runtime - when the job was started “finish_time”: “2025-10-23T21:59:44Z”, #Runtime - when the job was finished “status”: “finished”, #Runtime - Could be queued|running|finished|failed “process_id” : 134234 #Runtime - Process ID of the script monitoring claude “jobtype” : “claude”, #Config - right now we will only have claude jobs, but eventually we will also have jobs that invoke API calls to other AI models “LLM_process_id” : 134235 #Runtime - Process ID of the claude CLI or other LLM API “claude_command”: “code-researcher”,#Config - must match and existing claude command - required if the jobtype is claude “task_description” : “Config - Review the ModelSEEDpy codebase”, “supporting_data”: { “ModelSEEDpy directory” : “/home/chenry/projects/ClaudeProjects/ModelSEEDpy” }, #Config - data claude should use to support its operation “error”: None, #Runtime - Where error messages should be printed “output”: None #Runtime - Where output from cluade should go }

As the queue manager runs, it will first review all “running” jobs, which should all have process IDs in them. The queue manager will use the process IDs recorded in the jobs to ensure that all the jobs are still running. If a job in the “running_jobs” directory is no longer running, the job will be moved to the “failed_jobs” directory, and an error message will be added to the job indicating that the job crashed. Based on this analysis, the queue manager will update the count of currently running jobs and compare this count vs the worker count for the queue manager. If worker count is greater than the running jobs, the queue manager will check the “queued_jobs” directory for new jobs, and if a job is there, the queue manager will load the job file with the earliest modification time and use the job information to appropriately spin up a new worker harness instance to run the job. The job status will be reset to “running”, the process ID of the job will be set, and the job will be moved to the “running_jobs” directory. When this loop completes, the queue manager will update status.json, sleep for the specified rest interval, and then start the loop all over again. Worker harness: This is a python script that accepts a json file specifying a claude code “job” as input (see Job Manager PRD). The worker harness first validates the job file checking it against the json scheme for a job object. Next, the harness checks that the specified claude command in “claude_command” exists. If the specified command is not found, the job will be marked as failed with the “unknown agent type” error message. The worker will prompt the claude code CLI with this command, the “task” specified in the job, and the location of the supporting data as key value pairs. Claude output will be redirected to file. The worker will monitor claude until it stops running, capture the output piped out to a file by claude, then clean up the file. The file content will be saved to the job file under the key “output”. The worker will thenl update the job file with the new status (either “complete” or “failed” depending on the output the job that was run). The harness will also move the job file to the corresponding job directory (either “failed_jobs” or “finished_jobs”). Orchestrator: The orchestrator is the router for this framework. This system reads input from the inbox, interprets commands to create jobs, monitors job completion and sends responses to the outbox with results. This system will eventually manage workflows, but let’s leave this out of the implementation for now. /home/chenry/DropBox/AgentStore/projects/ / project.json #JSON file defining the project queued_prds/ .json #JSON file holding the PRD running_prds/ .json #JSON file holding the PRD and tasks finished_prds/ .json #JSON file holding the PRD, tasks, implementation report

Spec for user:

The spec for the project.json file looks like this: { “id” : “ModelSEEDpy”, “directory” : “/home/chenry/projects/ClaudeProjects/ModelSEEDpy”, “git_repository” : “https://github.com/cshenry/ModelSEEDpy” “create_time” : “2025-10-23T21:59:44Z”, “update_time” : “2025-10-23T21:59:44Z”, “description” : “Repository with ModelSEEDpy code for building models with the ModelSEED method” “owner” : “chenry”, “collaborators” : [“fliu”,”jplfaria”], “code_research_document” : “/home/chenry/projects/ClaudeProjects/ModelSEEDpy/MODELSEEDPY_CLAUDE_DOCUMENTATION.md” }

The spec for the PRD json files looks like this: { “id” : , “project” : “ModelSEEDpy”, “title” : “Improving MSExpression fit flux to expression function”, “version” : 1.0, “owner” : “chenry”, “status” : “draft”, #Could also be revising|development|testing|complete, “created_time”: “2025-10-23T21:59:44Z”, #When it was created “update_time” : “2025-10-23T21:59:44Z”, #When it was last updated “content” }

Slack Handler: Eventually, we will enable Slack to be used as an alternative to the CLI for querying the system state and communicating with the orchestrator. I already have a package that monitors slack channels and has many of the needed features. Let’s hold off on adapting that package until the rest of this framework is in place and tested.