Skip to content

multi agent scheduling - #27

Merged
TheHeroBrine422 merged 22 commits into
mainfrom
caleb/multi-agent-scheduling
Apr 26, 2026
Merged

multi agent scheduling#27
TheHeroBrine422 merged 22 commits into
mainfrom
caleb/multi-agent-scheduling

Conversation

@TheHeroBrine422

@TheHeroBrine422 TheHeroBrine422 commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

the easiest/best way to do have proper supervision between remote actors is to use an in memory cache of all the actors.

kameo/libp2p's swarm mDNS stuff is not 100% stable, so we need to do heartbeats to confirm if an actor still exists.

thankfully we can use link_remote and on_link_died, we just need to make sure the link doesnt die.

we can also use this to get a cache of current status anyway.

I made the in memory actor cache generic so we can use it for whatever in the future, and it has hooks to be able to get any data you want whenever it does a heartbeat.

scheduling across multiple agents is functional, but the code still has a lot of extra features that may need to be added.

todo:

  • heartbeat interval is hard set to 1 second, this might need to be modifiable. not sure if it should be a compile time or runtime thing.
  • likely need a way to query for VMs by agent. We either could include what agent a VM is currently running on in the GetVMInfo message, and/or could register vm's by hostname to the swarm.
    • i dont love using hostname in this way, because it requires hostnames to be unique, and I worry that a sysadmin/operator could accidentally make a mistake. I rather use a Ulid, but we need to have a conversation about this. odorobo-agent could also just auto configure the hostname to something guaranteed to be unique if we want.
  • this has no auto migration for if agents/vms go down. that needs to be added to the on_link_died handler. not going for no downtime, just want to autoreboot if a VM goes down.
  • the code probably just needs some clean up in general.

middle of starting.

Signed-off-by: Hero <caleb@calebgj.io>
…ents now but we still need something similar for vms.
testing.

Signed-off-by: Hero <caleb@calebgj.io>
the caches dont seem to be working the way i expect though. need to do
more testing and see if they are working correctly. I also just
generally don't trust on_link_died.

Signed-off-by: Hero <caleb@calebgj.io>
caches are working

Signed-off-by: Hero <caleb@calebgj.io>
placces.

Signed-off-by: Hero <caleb@calebgj.io>
I realized I can make this even better, and so I want to go through
another iteration, but I don't want to lose this version. squash this in
the actual merge.

Signed-off-by: Hero <caleb@calebgj.io>
Signed-off-by: Hero <caleb@calebgj.io>
Signed-off-by: Hero <caleb@calebgj.io>
@TheHeroBrine422 TheHeroBrine422 linked an issue Apr 21, 2026 that may be closed by this pull request
) -> Result<RemoteActorRef<AgentActor>, Report> {
loop {
let agent_actor_option = RemoteActorRef::<AgentActor>::lookup("agent").await?;
async fn lookup_by_actor_id(
self.agent_actor_cache.lock_data_cache().await.get(actor_id).map(|data| data.actor_ref.clone())
}

async fn lookup_by_hostname(
Comment thread odorobo-manager/src/actors/scheduler_actor.rs Fixed
// I am leaving it this way because I just wanted to get things working. We may need to change the way the data is stored in the future.
// My suggestions are either replacing it with a concurrent map, or using a RwLock. Either one might help, but I am not dealing with it now.
#[derive(Debug)]
pub struct ActorCache<ParentActor: Actor + RemoteActor, ChildActor: Actor + RemoteActor, Data: Clone + Send + Sync + 'static + fmt::Debug> {
Comment thread odorobo-shared/src/actor_cache/mod.rs Fixed
parent_actor_ref: ActorRef<ParentActor>,
data_cache: Arc<Mutex<AHashMap<ActorId, Data>>>,
keepalive_tasks: Arc<Mutex<AHashMap<ActorId, JoinHandle<()>>>>,
actor_finder: Option<JoinHandle<()>>,

let actor_cache = ActorCache {
parent_actor_ref: parent_actor_ref.clone(),
data_cache: data_cache,
let actor_cache = ActorCache {
parent_actor_ref: parent_actor_ref.clone(),
data_cache: data_cache,
keepalive_tasks: keepalive_tasks,
Comment thread odorobo-shared/src/actor_cache/mod.rs Fixed
Comment thread odorobo-shared/src/actor_cache/mod.rs Fixed
Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
in AgentStatus

Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
Comment thread odorobo-agent/src/actor/mod.rs Fixed
Comment thread odorobo-agent/src/actor/mod.rs Fixed
Comment thread odorobo-agent/src/actor/mod.rs Fixed
Comment thread odorobo-agent/src/actor/mod.rs Fixed
Comment thread odorobo-manager/src/actors/scheduler_actor.rs Fixed
Signed-off-by: Caleb Jones <caleb@calebgj.io>
@TheHeroBrine422

Copy link
Copy Markdown
Contributor Author

partially blocked by #19. placement groups and affinity is difficult to implement without modifying VmConfig, and I rather just write the meta-manifest and then add affinity stuff to that.

Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
/// additionally, because caleb is way too performance brained, he used integer math for the entire scoring algorithm just so we didnt have to convert to floats.
async fn schedule_agent(
&mut self,
msg: &CreateVM

#[derive(Debug)]
pub struct ActorCache<ParentActor: Actor + RemoteActor, ChildActor: Actor + RemoteActor, Data: Clone + Send + Sync + 'static + fmt::Debug> {
parent_actor_ref: ActorRef<ParentActor>,
@TheHeroBrine422
TheHeroBrine422 marked this pull request as ready for review April 26, 2026 13:36
@TheHeroBrine422
TheHeroBrine422 merged commit f2145d1 into main Apr 26, 2026
12 checks passed
@halfcyan
halfcyan deleted the caleb/multi-agent-scheduling branch July 10, 2026 05:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

multi-agent scheduling

2 participants