Skip to content

Commit af44a68

Browse files
committed
feat(agents): auto-register AgentConfig on first Ask (ApplyToPolicy now optional)
AskAsync/AskWithCallback register the built config with the global CoreAIAgent.Policy on first use, so the newcomer flow is just Build() -> Ask*() with no manual ApplyToPolicy(CoreAIAgent.Policy) step. Explicit ApplyToPolicy stays for custom policies and up-front registration; re-applying is idempotent. A null policy now reports an uninitialized lifetime scope instead of the misleading 'role not registered'.
1 parent 4af62fb commit af44a68

4 files changed

Lines changed: 40 additions & 11 deletions

File tree

Assets/CoreAI/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
## [Unreleased]
44

5+
- **`AgentBuilder`: `ApplyToPolicy` is now optional.** `AskAsync`/`AskWithCallback` auto-register the built
6+
`AgentConfig` with the global `CoreAIAgent.Policy` on first use, so the newcomer flow is just `Build()`
7+
`Ask*()` — no manual `ApplyToPolicy(CoreAIAgent.Policy)` step. The explicit call is still available for
8+
custom policies or up-front registration; re-applying is idempotent. A null policy (uninitialized lifetime
9+
scope) now fails with a clearer message than the old "role not registered".
10+
- **Benchmark: G7 no longer captures a scene screenshot.** The comprehensive-integration (Player/Gate/Key)
11+
scenario photographed as an unreadable composite of overlapping primitives and floating world-space labels
12+
that added nothing to the score. G6 (the free-build castle) is now the only hero image; G7 is graded purely
13+
on world state + Lua consistency, like the other logic groups.
514
- **Structured world spawning.** `world_command` `spawn`, `spawn_batch`, and `change` expose
615
`worldPositionStays` (default `false`). Parented transforms are local by default; callers can pass `true`
716
to preserve world space. The tool contract now recommends named `empty` roots and meaningful child

Assets/CoreAI/Docs/AGENT_BUILDER.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,13 +339,16 @@ Remember what the player bought using memory.")
339339
.WithChatHistory()
340340
.Build();
341341

342-
// 2. Register (via global CoreAIAgent.Policy or your own policy)
343-
blacksmith.ApplyToPolicy(CoreAIAgent.Policy);
344-
345-
// 3. Invoke (one line!)
342+
// 2. Invoke (one line!) — the first Ask auto-registers the agent with the global
343+
// CoreAIAgent.Policy, so no manual registration step is needed.
346344
blacksmith.AskWithCallback("What do you have?");
347345
```
348346

347+
> **`ApplyToPolicy` is now optional.** `AskAsync`/`AskWithCallback` register the built config with the
348+
> global `CoreAIAgent.Policy` on first use, so newcomers can go straight from `Build()` to `Ask*()`.
349+
> Call `blacksmith.ApplyToPolicy(policy)` explicitly only when you target a **custom** `AgentMemoryPolicy`,
350+
> or want the role registered up front (e.g. before routing a task to it through the orchestrator directly).
351+
349352
### Recipe 2: Storyteller (chat only, no tools)
350353

351354
```csharp

Assets/CoreAI/Runtime/Core/Features/AgentMemory/AgentBuilder.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,12 @@ public sealed class AgentConfig
690690

691691
/// <summary>
692692
/// Applies this built agent configuration to a mutable <see cref="AgentMemoryPolicy"/>.
693+
/// <para>
694+
/// For the common case you do NOT need to call this: <c>AskAsync</c>/<c>AskWithCallback</c>
695+
/// auto-register the config with the global <see cref="CoreAIAgent.Policy"/> on first use.
696+
/// Call this explicitly only when targeting a custom policy, or to register the role up front
697+
/// (e.g. so the orchestrator can route to it before the first ask).
698+
/// </para>
693699
/// </summary>
694700
public void ApplyToPolicy(AgentMemoryPolicy policy)
695701
{

Assets/CoreAI/Runtime/Core/Features/AgentMemory/AgentConfigExtensions.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@ public static Task<string> AskAsync(
4040
int priority = 0,
4141
CancellationToken cancellationToken = default)
4242
{
43-
// Validate the agent config (role registration) before infrastructure state so an
44-
// unregistered role fails with a clear "not registered" message regardless of whether
45-
// the orchestrator happens to be initialized yet.
46-
ValidateRoleRegistered(config);
43+
// Make sure the role is known to the global policy before we run. For the common newcomer
44+
// flow this AUTO-REGISTERS the built config, so `Build()` + `Ask*()` just works without an
45+
// explicit `ApplyToPolicy(CoreAIAgent.Policy)` call. Done before the orchestrator null-check
46+
// so a missing lifetime scope still surfaces its own clear message.
47+
EnsureRoleRegistered(config);
4748

4849
if (orchestrator == null)
4950
{
@@ -61,18 +62,28 @@ public static Task<string> AskAsync(
6162
}, cancellationToken);
6263
}
6364

64-
private static void ValidateRoleRegistered(AgentConfig config)
65+
private static void EnsureRoleRegistered(AgentConfig config)
6566
{
6667
if (string.IsNullOrWhiteSpace(config?.RoleId))
6768
{
6869
throw new InvalidOperationException("Role id is missing. Provide RoleId in AgentBuilder.");
6970
}
7071

7172
AgentMemoryPolicy policy = CoreAIAgent.Policy;
72-
if (policy == null || !policy.HasRole(config.RoleId))
73+
if (policy == null)
7374
{
7475
throw new InvalidOperationException(
75-
$"Role '{config.RoleId}' is not registered in CoreAIAgent.Policy. Call config.ApplyToPolicy(CoreAIAgent.Policy) (or Use BuildDetached() + explicit ApplyToPolicy()).");
76+
$"Cannot run agent '{config.RoleId}': CoreAIAgent.Policy is null. Initialize CoreAI first " +
77+
"(add CoreAILifetimeScope to the scene / run CoreAI setup) before asking an agent.");
78+
}
79+
80+
// Convenience: register the built config with the global policy on first use, so newcomers
81+
// do not have to call ApplyToPolicy(CoreAIAgent.Policy) by hand. Re-applying is idempotent;
82+
// advanced users targeting a CUSTOM AgentMemoryPolicy still call ApplyToPolicy on that policy
83+
// themselves (and, once registered here, this no-ops).
84+
if (!policy.HasRole(config.RoleId))
85+
{
86+
config.ApplyToPolicy(policy);
7687
}
7788
}
7889

0 commit comments

Comments
 (0)