Skip to content

Commit 898c56c

Browse files
committed
Add meta-harness user-agent dimension for omnigent
Detect the OMNIGENT environment variable and report meta-harness/omnigent as an independent user-agent dimension, parallel to agent detection. This lets the platform see both the meta-harness (omnigent) and the underlying coding agent (e.g. claude-code) in the same request. Co-authored-by: Isaac Signed-off-by: simon <simon.faltum@databricks.com>
1 parent 1f0160e commit 898c56c

3 files changed

Lines changed: 115 additions & 0 deletions

File tree

NEXT_CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### New Features and Improvements
66

7+
- Added a `meta-harness` user-agent dimension that reports the omnigent meta-harness (detected via the `OMNIGENT` environment variable) independently of agent detection.
8+
79
### Breaking Changes
810

911
### Bug Fixes

databricks-sdk-java/src/main/java/com/databricks/sdk/core/UserAgent.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ public static String asString() {
133133
if (!agent.isEmpty()) {
134134
segments.add(String.format("agent/%s", agent));
135135
}
136+
String metaHarness = metaHarnessProvider();
137+
if (!metaHarness.isEmpty()) {
138+
segments.add(String.format("meta-harness/%s", metaHarness));
139+
}
136140
// Concurrent iteration over ArrayList must be guarded with synchronized.
137141
synchronized (otherInfo) {
138142
segments.addAll(
@@ -174,6 +178,8 @@ private static List<CicdProvider> listCiCdProviders() {
174178

175179
protected static volatile String agentProvider = null;
176180

181+
protected static volatile String metaHarnessProvider = null;
182+
177183
protected static Environment env = null;
178184

179185
// Represents an environment variable with its name and expected value
@@ -362,6 +368,47 @@ private static String agentProvider() {
362368
return agentProvider;
363369
}
364370

371+
// Describes a single meta-harness: the env var that identifies it and the
372+
// product name reported in the user agent.
373+
private static class KnownMetaHarness {
374+
private final String envVar;
375+
private final String product;
376+
377+
KnownMetaHarness(String envVar, String product) {
378+
this.envVar = envVar;
379+
this.product = product;
380+
}
381+
}
382+
383+
// Canonical list of known meta-harnesses, detected by presence.
384+
// Keep in sync with databricks-sdk-go and databricks-sdk-py.
385+
// OMNIGENT is set by the omnigent meta-harness (https://github.com/omnigent-ai/omnigent).
386+
private static List<KnownMetaHarness> listKnownMetaHarnesses() {
387+
return Arrays.asList(new KnownMetaHarness("OMNIGENT", "omnigent"));
388+
}
389+
390+
// Looks up the active meta-harness by env var presence, independent of the agent.
391+
private static String lookupMetaHarnessProvider(Environment env) {
392+
for (KnownMetaHarness h : listKnownMetaHarnesses()) {
393+
if (env.get(h.envVar) != null) {
394+
return h.product;
395+
}
396+
}
397+
return "";
398+
}
399+
400+
// Thread-safe lazy initialization of meta-harness detection
401+
private static String metaHarnessProvider() {
402+
if (metaHarnessProvider == null) {
403+
synchronized (UserAgent.class) {
404+
if (metaHarnessProvider == null) {
405+
metaHarnessProvider = lookupMetaHarnessProvider(env());
406+
}
407+
}
408+
}
409+
return metaHarnessProvider;
410+
}
411+
365412
private static Environment env() {
366413
if (env == null) {
367414
env =

databricks-sdk-java/src/test/java/com/databricks/sdk/core/UserAgentTest.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ void tearDown() {
1818
private void setupAgentEnv(Map<String, String> envMap) {
1919
UserAgent.agentProvider = null;
2020
UserAgent.cicdProvider = null;
21+
UserAgent.metaHarnessProvider = null;
2122
UserAgent.env = new Environment(envMap, new ArrayList<>(), System.getProperty("os.name"));
2223
}
2324

2425
private void cleanupAgentEnv() {
2526
UserAgent.env = null;
2627
UserAgent.agentProvider = null;
2728
UserAgent.cicdProvider = null;
29+
UserAgent.metaHarnessProvider = null;
2830
}
2931

3032
@Test
@@ -617,4 +619,68 @@ public void testAgentProviderCached() {
617619
Assertions.assertTrue(UserAgent.asString().contains("agent/cursor"));
618620
Assertions.assertFalse(UserAgent.asString().contains("agent/claude-code"));
619621
}
622+
623+
@Test
624+
public void testMetaHarnessProviderOmnigent() {
625+
setupAgentEnv(
626+
new HashMap<String, String>() {
627+
{
628+
put("OMNIGENT", "1");
629+
}
630+
});
631+
Assertions.assertTrue(UserAgent.asString().contains("meta-harness/omnigent"));
632+
}
633+
634+
@Test
635+
public void testMetaHarnessProviderNoHarness() {
636+
setupAgentEnv(new HashMap<>());
637+
Assertions.assertFalse(UserAgent.asString().contains("meta-harness/"));
638+
}
639+
640+
@Test
641+
public void testMetaHarnessProviderEmptyValueStillSet() {
642+
// Empty string still counts as "set" for presence-only detection,
643+
// matching the agent dimension and databricks-sdk-go semantics.
644+
setupAgentEnv(
645+
new HashMap<String, String>() {
646+
{
647+
put("OMNIGENT", "");
648+
}
649+
});
650+
Assertions.assertTrue(UserAgent.asString().contains("meta-harness/omnigent"));
651+
}
652+
653+
@Test
654+
public void testMetaHarnessProviderIndependentOfAgent() {
655+
// Under omnigent both OMNIGENT and the agent marker are set: report both
656+
// dimensions, and the meta-harness must not trip the agent "multiple" logic.
657+
setupAgentEnv(
658+
new HashMap<String, String>() {
659+
{
660+
put("OMNIGENT", "1");
661+
put("CLAUDECODE", "1");
662+
}
663+
});
664+
String userAgent = UserAgent.asString();
665+
Assertions.assertTrue(userAgent.contains("agent/claude-code"));
666+
Assertions.assertTrue(userAgent.contains("meta-harness/omnigent"));
667+
Assertions.assertFalse(userAgent.contains("agent/multiple"));
668+
}
669+
670+
@Test
671+
public void testMetaHarnessProviderCached() {
672+
// Set up with omnigent.
673+
setupAgentEnv(
674+
new HashMap<String, String>() {
675+
{
676+
put("OMNIGENT", "1");
677+
}
678+
});
679+
Assertions.assertTrue(UserAgent.asString().contains("meta-harness/omnigent"));
680+
681+
// Change env after caching. Cached result should persist.
682+
UserAgent.env =
683+
new Environment(new HashMap<>(), new ArrayList<>(), System.getProperty("os.name"));
684+
Assertions.assertTrue(UserAgent.asString().contains("meta-harness/omnigent"));
685+
}
620686
}

0 commit comments

Comments
 (0)