Best Practices for Prompt Engineering and Agent Configuration in LMForge

LMForge structures every agent as three configurable layers—system prompt, preset prompt, and contextual prompt—while enforcing strict validation on token limits, iteration counts, and tool whitelisting to ensure deterministic, safe AI behavior.

Effective prompt engineering and agent configuration in LMForge require understanding how the platform separates static instructions from dynamic context. The repository haohao-end/lmforge-end-to-end-llmops-platform-for-multi-model-agents implements this architecture in api/internal/core/agent/entities/agent_entity.py, allowing developers to tune global behavior, application personality, and conversation history independently. Mastering these layers ensures your agents remain within token budgets while maximizing tool-use accuracy.

Understanding the Three-Layer Prompt Architecture

LMForge agents combine three distinct prompt layers that are merged at runtime. This separation allows you to update application personality without touching system logic, or adjust memory settings without rewriting prompts.

System Prompt Layer

The system prompt defines global behavior, tool-use policies, and response formats. In agent_entity.py (lines 10-38), LMForge provides two base templates: AGENT_SYSTEM_PROMPT_TEMPLATE for standard agents and REACT_AGENT_SYSTEM_PROMPT_TEMPLATE for ReACT-style tool use. These templates contain explicit placeholders such as {preset_prompt}, {long_term_memory}, and {tool_description} that the platform injects at runtime.

Preset Prompt Layer

The preset prompt stores customer-specific instructions that define an application's "personality." Stored in the App config via app_service.py (lines 97-106), this field is validated to ensure it does not exceed 2000 characters (lines 795-796). Keeping preset prompts concise prevents token-budget overflow while allowing product teams to customize tone and domain focus without engineering changes.

Contextual Prompt Layer

The contextual prompt comprises short-term conversation history, long-term memory summaries, and retrieved knowledge. The TokenBufferMemory.get_history_prompt_messages method in token_buffer_memory.py (lines 24-63) handles token-aware trimming, ensuring the LLM receives only the most recent relevant dialogue while staying within the model's context window.

Prompt Engineering Best Practices for LMForge Agents

Following these ten practices ensures your agents operate reliably within LMForge's guardrails.

  • Use a clear system-prompt template. Keep language concise, enumerate rules explicitly, and include placeholders for {preset_prompt} and {long_term_memory}. This guarantees the LLM receives a deterministic frame each turn.

  • Validate preset-prompt length. Enforce the 2000-character maximum in app_service.py to prevent token-budget overflow and maintain model performance.

  • Trim historic messages by token count. Configure TokenBufferMemory with a max_token_limit (default 2000) to ensure the LLM sees only recent, relevant dialogue.

  • Inject long-term memory conditionally. Enable this only via AgentConfig.enable_long_term_memory to avoid unnecessary prompt bloat for stateless agents.

  • Leverage tool-call features. Pass ModelFeature.TOOL_CALL and ModelFeature.AGENT_THOUGHT when constructing the LLM instance to enable JSON-structured tool execution.

  • Separate optimization from generation. Use AIService.optimize_prompt with its dedicated OPTIMIZE_PROMPT_TEMPLATE (defined in ai_entity.py) to polish user prompts without affecting the main agent flow.

  • Define tools declaratively. Populate AgentConfig.tools with BaseTool subclasses to ensure only whitelisted tools are reachable during a session.

  • Set a safe max-iteration count. Configure AgentConfig.max_iteration_count (default 5) to prevent runaway loops during tool-call chains.

  • Version-control all templates. Keep prompt templates as constants in source files (e.g., agent_entity.py) rather than database records to ensure reproducibility and auditability.

Configuring Agent Runtime Parameters

The AgentConfig class in agent_entity.py (lines 91-108) serves as the central configuration object. Instantiate it with validated parameters to ensure safe execution.

from uuid import UUID
from langchain_core.tools import BaseTool
from internal.core.agent.entities.agent_entity import AgentConfig, AGENT_SYSTEM_PROMPT_TEMPLATE

# 1️⃣ Identify the user & source

user_id: UUID = ...   # from authentication

invoke_source = "WEB_APP"  # or other enum value

# 2️⃣ Prepare a concise preset prompt (<2k chars)

preset = """You are a travel‑assistant that only recommends eco‑friendly destinations. \
Only reply in English and list up to three options with short (≤50 words) descriptions."""

# 3️⃣ Choose enabled features

enable_memory = True               # long‑term memory flag

tools: list[BaseTool] = [...]      # e.g. dataset_retrieval, google_search

# 4️⃣ Build the AgentConfig

config = AgentConfig(
    user_id=user_id,
    invoke_from=invoke_source,
    max_iteration_count=5,
    system_prompt=AGENT_SYSTEM_PROMPT_TEMPLATE,   # default system frame

    preset_prompt=preset,
    enable_long_term_memory=enable_memory,
    tools=tools,
    review_config={"review_required": False},
)

All fields are validated by Pydantic; the platform automatically inserts preset_prompt into the system template before the LLM call.

Implementing Tool-Call Agents

For agents requiring tool use, LMForge provides ReactAgent in react_agent.py. This class automatically injects ModelFeature.TOOL_CALL and uses REACT_AGENT_SYSTEM_PROMPT_TEMPLATE to instruct the model on JSON tool-call formatting.

from internal.core.agent.agents.react_agent import ReactAgent
from internal.core.agent.entities.agent_entity import AgentConfig
from internal.core.tools.builtin_tools.providers.google_search import GoogleSearchTool

# 1️⃣ Define tools

search_tool = GoogleSearchTool()   # implements BaseTool, safe‑sandboxed wrapper

# 2️⃣ Build config

cfg = AgentConfig(
    user_id=current_user.id,
    invoke_from="WEB_APP",
    preset_prompt="You are a finance‑assistant focused on personal budgeting.",
    tools=[search_tool],
    enable_long_term_memory=False,
)

# 3️⃣ Instantiate the agent

agent = ReactAgent(cfg, db=db, conversation=conv)

# 4️⃣ Run a single step (the platform loops internally)

output = agent.run_step(user_input="How can I save on groceries this month?")
print(output)

The ReactAgent automatically handles the ReACT loop, parsing JSON tool calls and executing them against the whitelisted tools defined in AgentConfig.tools.

Summary

  • Separate prompt concerns into system, preset, and contextual layers to enable independent updates without breaking agent workflows.
  • Enforce length limits on preset prompts (2000 characters) and conversation history (token-based trimming via TokenBufferMemory) to prevent context window overflow.
  • Configure runtime safety via AgentConfig parameters including max_iteration_count (default 5) and explicit tool whitelisting.
  • Leverage built-in optimization through AIService.optimize_prompt for polishing user prompts without affecting production agent flows.
  • Version-control templates by keeping system prompts as code constants in agent_entity.py rather than database records.

Frequently Asked Questions

What is the maximum length for preset prompts in LMForge?

LMForge enforces a 2000-character limit on preset prompts. This validation occurs in app_service.py (lines 795-796) during app configuration. Exceeding this limit raises a validation error to prevent token-budget overflow and ensure the combined system and preset prompts fit within the model's context window.

How does LMForge prevent token overflow in conversation history?

The platform uses TokenBufferMemory.get_history_prompt_messages in token_buffer_memory.py (lines 24-63) to trim historic messages. This method calculates token counts for each message and removes oldest entries once the max_token_limit (default 2000) is reached. This ensures the LLM receives only the most recent, relevant dialogue while staying within context limits.

What is the default maximum iteration count for agents?

LMForge sets a default max_iteration_count of 5 in AgentConfig (agent_entity.py, lines 91-108). This safety bound prevents runaway loops when agents repeatedly invoke tools or self-refine. When this limit is reached, the platform returns MAX_ITERATION_RESPONSE to signal the front-end that the agent has stopped to prevent infinite recursion.

How do I enable long-term memory for an agent?

Enable long-term memory by setting enable_long_term_memory=True in AgentConfig. When enabled, the platform injects memory content into the {long_term_memory} placeholder in the system prompt template. This feature should only be activated for agents requiring stateful context, as it increases prompt size. Stateless agents should leave this disabled to minimize token consumption.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →