HTN Planner reference

This chapter collects the runtime configuration keys, what you can rely on versus must not assume, the troubleshooting table, and an overview of the programmatic API entry points.

Settings Registry

Runtime key prefix: /O3DE/Gems/HtnPlanner/Runtime/ (defaults in the Gem’s Registry/htnplanner.setreg).

KeyDefaultPurpose
GlobalPlanningStepsPerFrame2048Global per-frame DFS step budget (handed to agents in FIFO rotation)
MaxDecompositionStepsPerPlan4096Default per-solve step cap (agents can override)
DefaultReplanIntervalSeconds0.5Default opportunistic/continuous replan throttle
ReplanBackoffInitialSeconds / ReplanBackoffMaxSeconds0.5 / 5.0Failure backoff envelope
EnableStatstrueGlobal statistics toggle for htn_dumpStats

Compile-time key: /O3DE/Gems/HtnPlanner/Compiler/ComplexityWarnThreshold (V15 complexity warning threshold, default 4096).

The planning budget has two layers: the agent’s Max Decomposition Steps caps a single solve, while GlobalPlanningStepsPerFrame caps the combined per-frame consumption of all agents. The former guards against a single exploding domain, the latter controls frame cost.

Capability limits

You can rely on:

  • Deterministic planning, with time-sliced scheduling byte-identical to a one-shot solve;
  • Domain hot reload with WorldState migration for same-name, same-type keys;
  • Three operator extension channels and Domain Import of zero-parameter compound tasks;
  • Built-in Wait / SetWorldState / LogMessage / script bridges; Canvas validation and trace replay.

Do not assume:

  • Operators move the entity for you (implement or bridge motion yourself, e.g. via the Navigation3D adapter);
  • WorldState syncs across multiplayer clients (the authority owns the agent; operators do their own RPCs);
  • A string passed from script becomes a String value (default boxing is Tag/Crc32 unless the key type is declared String);
  • Editing a .htnnode refreshes an already-open Canvas palette (reopen the document or restart Canvas);
  • Graphs can be edited node-by-node at runtime (not in v1; edit the source asset → recompile → hot reload is the intended path).

Explicitly out of scope for v1: GOAP / behavior-tree hybrids, multi-agent joint planning, LLM integration, built-in multiplayer WorldState sync.

Troubleshooting

SymptomLikely causeWhat to try
Agent never actsDomain not compiled / Auto Start off / wrong Root TaskCheck AssetProcessor; check NoPlan in htn_dumpStats; confirm a Domain is assigned (and it is the .htndomain_compiled product)
Always NoPlanPreconditions never trueVerify Externally Written keys really have sensors writing them; inspect values in the ImGui panel
Frequent replans / thrashWorldState rewritten every frameRaise Replan Interval; reduce noisy keys
StepLimitExceededMethod tree too deep/wideFix V15 warnings first; raise Max Decomposition Steps only if genuinely needed
Script operator stuckCompletion never reported, or stale tokenCall HtnCompleteCurrentOperator with the token received in Begin
Import fails V11Bad path / non-zero-parameter import / import cycleFix the Domain Import (project-relative path, zero-parameter compound task); make sure imported domains compile first
Macro fails V10Macro references a macro / an unregistered nodeMacro subtasks[].node may only be a registered operator or operator-preset id
Canvas palette stale after .htnnode editRegistry rescan timingReopen the document or restart Canvas; AssetProcessor rebuilds Domains automatically
Hitching with many agentsGlobal planning budget under pressureWatch per-frame steps in htn_dumpStats; adjust via htn_setPlanningBudget or the Settings Registry

Programmatic API overview

The planning core is pure C++ with no editor dependencies, callable without components or assets—useful for unit tests, tools, and programmatic domain construction. Public headers live under HtnPlanner/:

Entry pointHeaderPurpose
FindPlan(domainView, worldState, rootTask, settings)HtnPlanning.hOne-shot solve; returns Plan + MTR + optional trace; byte-identical to runtime incremental planning
HtnDomainBuilderUtilHtnDomainBuilderUtil.hFluent recording + Build() flattening for programmatic Domains (AddKey / BeginCompound / BeginMethod / AddSubtask / BeginPrimitive / AddCompare / AddEffect / SetRootTask)
HtnLinkedDomainViewHtnDomain.hImport-linked domain view; obtain it from an asset via HtnDomainAsset::GetLinkedView()
IHtnSystem (AZ::Interface)HtnPlannerBus.hGlobal singleton surface: SetGlobalPlanningBudget / GetStats / SetDebugAgent / DumpRecordedTraces

Minimal example:

using namespace HtnPlanner;

HtnDomainBuilderUtil builder;
builder.AddKey("EnemyVisible", HtnValueType::Bool, HtnValue(false));
builder.BeginCompound("Root");
builder.BeginMethod("Engage");
builder.AddCompare("EnemyVisible", HtnCompareOp::Equal, HtnDomainBuilderUtil::Lit(HtnValue(true)));
builder.AddSubtask("Attack");
builder.SetRootTask("Root");
// . BeginPrimitive / AddEffect .

HtnDomain domain;
AZStd::vector<AZStd::string> errors;
builder.Build(domain, &errors);

HtnLinkedDomainView view(domain);
HtnWorldState state;
state.Initialize(view.GetUnifiedSchema());
state.SetValue(AZ::Crc32("EnemyVisible"), HtnValue(true));

HtnPlanningSettings settings;
const HtnTaskIndex root = domain.FindTaskByName(AZ::Crc32("Root")).value();
HtnPlanResult result = FindPlan(view, state, root, settings);

See the programmatic API section above for the primary builder entry points.

Further reading

  • Navigation3D: optional Nav3D.* operators when both Gems are enabled.
  • Dawn Stream: remotely review levels that include HTN-driven agents.

Copyright © 2026 DawnEngine. All rights reserved.

DawnEngine is a commercial 3D engine distributed under the DawnEngine end-user license agreement. Engine binaries and source are proprietary and are not covered by the licenses below.

Documentation only: the prose and templates on this site are a derivative work of Open 3D Engine (O3DE) documentation by the O3DE Contributors, used under CC BY 4.0 (documentation content), Apache 2.0 (site code), and the MIT license (inline code samples).

The open-source 3D engine that DawnEngine is built on top of is Open 3D Engine . DawnEngine is not affiliated with, endorsed by, or sponsored by The Linux Foundation or the O3DE project. “O3DE” and “Open 3D Engine” are trademarks of The Linux Foundation.