ADK.InstructionCompiler (ADK v0.0.1-alpha.1)

Copy Markdown View Source

Compiles the system instruction for an LLM agent by combining:

  • Global instruction (from agent or parent)
  • Agent's own instruction (with template variable substitution from state)
  • Identity/persona instruction
  • Output schema instruction
  • Transfer instructions (listing available sub-agents)

This mirrors Python ADK's BaseLlmFlow._compile_system_instruction().

InstructionProvider

Both the instruction and global_instruction fields on ADK.Agent.LlmAgent support dynamic providers in addition to static strings:

  • String.t() — static instruction (existing behaviour, unchanged)
  • (ADK.Context.t() -> String.t()) — 1-arity anonymous function called at runtime
  • {module, atom} — MFA with 1 arg (context appended): module.atom(ctx)
  • {module, atom, extra_args} — MFA with extra args (context prepended): module.atom(ctx, extra_args...)

The provider is called once per invocation, just before template-variable substitution, so the returned string still supports {variable} interpolation.

If a provider returns a non-binary value, it is coerced via to_string/1. If the provider raises, the error is logged and an empty string is used so the agent can still respond.

Summary

Functions

Compile the full system instruction for an agent given the context.

Split compiled instructions into static and dynamic portions.

Resolve an instruction provider to a string.

Substitute template variables in an instruction string.

Functions

compile(agent, ctx)

@spec compile(map(), ADK.Context.t()) :: String.t()

Compile the full system instruction for an agent given the context.

Returns a single string combining all instruction components.

compile_split(agent, ctx)

@spec compile_split(map(), ADK.Context.t()) :: {String.t(), String.t()}

Split compiled instructions into static and dynamic portions.

  • Static: Parts that don't change between requests — global instruction, identity, transfer instructions. Suitable for Gemini's context caching.
  • Dynamic: Parts that change per request — agent instruction with state variable substitution, output schema instruction.

Returns {static_instruction, dynamic_instruction} where either may be an empty string (but never nil).

resolve_provider(instruction, ctx)

@spec resolve_provider(term(), ADK.Context.t() | nil) :: String.t() | nil

Resolve an instruction provider to a string.

Handles:

  • String.t() — returned as-is
  • (ctx -> String.t()) — called with the context (may be nil for global)
  • {module, atom} — called as module.atom(ctx)
  • {module, atom, extra_args} — called as module.atom(ctx, extra_args...)

Non-binary return values are coerced via to_string/1. Errors are caught and an empty string is returned (with a warning logged).

substitute_vars(instruction, state)

@spec substitute_vars(String.t(), map()) :: String.t()

Substitute template variables in an instruction string.

Variables use the {key} syntax. Values are looked up from session state.

Examples

iex> ADK.InstructionCompiler.substitute_vars("Hello {name}!", %{"name" => "World"})
"Hello World!"

iex> ADK.InstructionCompiler.substitute_vars("No vars here", %{})
"No vars here"