Skip to content

Commit 6fdb204

Browse files
committed
fix(registry): add team index for dapr-agents compatibility
The registerAgent method was only saving per-agent metadata keys but not updating the team index at agents:{team}:_index. This index is how dapr-agents discovers peers in multi-agent workflows. Now follows the same two-step registration protocol as dapr-agents: 1. Save per-agent metadata key (agents:{team}:{name}) 2. Update team index (agents:{team}:_index) with agent name list Also adds partitionKey to state metadata for partitioned stores. Signed-off-by: Javier Aliaga <javier@diagrid.io>
1 parent c216390 commit 6fdb204

File tree

2 files changed

+75
-5
lines changed

2 files changed

+75
-5
lines changed

quarkus/quarkus-agentic-dapr-agents-registry/src/main/java/io/quarkiverse/dapr/agents/registry/service/AgentRegistry.java

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
package io.quarkiverse.dapr.agents.registry.service;
1515

1616
import io.dapr.client.DaprClient;
17+
import io.dapr.client.domain.GetStateRequest;
18+
import io.dapr.client.domain.State;
19+
import io.dapr.utils.TypeRef;
1720
import io.quarkiverse.dapr.agents.registry.model.AgentMetadata;
1821
import io.quarkiverse.dapr.agents.registry.model.AgentMetadataSchema;
1922
import io.quarkus.runtime.StartupEvent;
@@ -31,6 +34,7 @@
3134
import java.lang.reflect.Type;
3235
import java.time.Instant;
3336
import java.util.ArrayList;
37+
import java.util.HashMap;
3438
import java.util.HashSet;
3539
import java.util.List;
3640
import java.util.Map;
@@ -254,14 +258,57 @@ private static <T> T invokeMethod(Annotation ann, String methodName, Class<T> re
254258
}
255259

256260
/**
257-
* Registers an agent schema in the Dapr state store.
261+
* Registers an agent schema in the Dapr state store and updates the team index.
262+
*
263+
* <p>Two-step operation matching the Python dapr-agents registration protocol:
264+
* <ol>
265+
* <li>Save per-agent metadata key ({@code agents:{team}:{name}})</li>
266+
* <li>Update the team index key ({@code agents:{team}:_index}) adding this agent name</li>
267+
* </ol>
268+
*
269+
* <p>The team index is how dapr-agents discovers peers in multi-agent workflows.
258270
*
259271
* @param schema the agent metadata schema to register
260272
*/
273+
@SuppressWarnings("unchecked")
261274
public void registerAgent(AgentMetadataSchema schema) {
262-
String key = "agents:" + team + ":" + schema.getName();
263-
LOG.infof("Registering agent: %s", key);
264-
client.saveState(statestore, key, null, schema,
265-
Map.of("contentType", "application/json"), null).block();
275+
String registryPrefix = "agents:" + team;
276+
Map<String, String> meta = Map.of(
277+
"contentType", "application/json",
278+
"partitionKey", registryPrefix);
279+
280+
// Step 1: Save per-agent metadata key
281+
String agentKey = registryPrefix + ":" + schema.getName();
282+
LOG.infof("Registering agent: %s", agentKey);
283+
client.saveState(statestore, agentKey, null, schema, meta, null).block();
284+
285+
// Step 2: Update team index (adds agent name to the list)
286+
String indexKey = registryPrefix + ":_index";
287+
GetStateRequest getRequest = new GetStateRequest(statestore, indexKey)
288+
.setMetadata(meta);
289+
State<Map> indexState = client.getState(getRequest, TypeRef.get(Map.class)).block();
290+
291+
Map<String, Object> indexData;
292+
if (indexState != null && indexState.getValue() != null) {
293+
indexData = new HashMap<>((Map<String, Object>) indexState.getValue());
294+
} else {
295+
indexData = new HashMap<>();
296+
}
297+
298+
List<String> agentsList;
299+
Object existing = indexData.get("agents");
300+
if (existing instanceof List) {
301+
agentsList = new ArrayList<>((List<String>) existing);
302+
} else {
303+
agentsList = new ArrayList<>();
304+
}
305+
306+
if (!agentsList.contains(schema.getName())) {
307+
agentsList.add(schema.getName());
308+
indexData.put("agents", agentsList);
309+
String etag = (indexState != null) ? indexState.getEtag() : null;
310+
client.saveState(statestore, indexKey, etag, indexData, meta, null).block();
311+
LOG.infof("Updated team index '%s' with agent '%s'", indexKey, schema.getName());
312+
}
266313
}
267314
}

quarkus/quarkus-agentic-dapr-agents-registry/src/test/java/io/quarkiverse/dapr/agents/registry/service/AgentRegistryDevServicesTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
import jakarta.inject.Inject;
88
import org.junit.jupiter.api.Test;
99

10+
import io.dapr.utils.TypeRef;
11+
1012
import java.time.Duration;
13+
import java.util.List;
14+
import java.util.Map;
1115

1216
import static org.assertj.core.api.Assertions.assertThat;
1317
import static org.awaitility.Awaitility.await;
@@ -117,4 +121,23 @@ void allAutoDiscoveredAgentsShouldHaveConsistentMetadata() {
117121
}
118122
});
119123
}
124+
125+
@SuppressWarnings("unchecked")
126+
@Test
127+
void teamIndexShouldContainAllRegisteredAgents() {
128+
String[] expectedAgents = {"test-agent-with-prompt", "test-agent-simple", "TestAgent.defaultNameAgent"};
129+
130+
await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> {
131+
State<Map> indexState = daprClient.getState(
132+
STATE_STORE, "agents:" + TEAM + ":_index", TypeRef.get(Map.class)).block();
133+
assertThat(indexState).isNotNull();
134+
assertThat(indexState.getValue()).isNotNull();
135+
136+
Map<String, Object> indexData = (Map<String, Object>) indexState.getValue();
137+
assertThat(indexData).containsKey("agents");
138+
139+
List<String> agentsList = (List<String>) indexData.get("agents");
140+
assertThat(agentsList).containsExactlyInAnyOrder(expectedAgents);
141+
});
142+
}
120143
}

0 commit comments

Comments
 (0)