Downcity
Local Agent

Agent Constructor Options

Detailed explanation of the local Agent id, path, instruction, model, env, tools, and plugins options

Agent Constructor Options

The local Agent is constructed like this:

new Agent({
  id,
  path,
  model,
  env,
  instruction,
  tools,
  plugins,
})

id

The stable identifier of the agent.

It affects the SDK session storage path:

<projectRoot>/.downcity/agents/<agentId>/...

Recommended properties:

  • stable
  • URL-safe
  • not changed casually

That is because it directly controls the session storage partition.

path

The project root directory bound to the current agent.

The SDK uses it to:

  • load project config
  • organize session storage

If path is wrong, many later behaviors will feel confusing because the agent will read config and write data in the wrong context.

instruction

Static caller-provided instructions for the local SDK Agent.

new Agent({
  id: "repo-helper",
  path: "/path/to/project",
  instruction: [
    "You are a concise code assistant.",
    "Prefer direct file references when explaining code.",
  ],
});

Key points:

  • instruction is static and cache-friendly
  • the SDK does not render dynamic variables inside it
  • the SDK does not read PROFILE.md or SOUL.md by itself
  • if you omit instruction, the SDK uses its minimal core instruction fallback

If a host such as city wants project markdown files to affect the agent, that host should read those files and pass their final text through instruction.

model

The default LanguageModel instance for sessions created under this agent.

new Agent({
  id: "repo-helper",
  path: "/path/to/project",
  model: openai.responses("gpt-5"),
});

Key points:

  • the SDK does not resolve provider or model IDs for you
  • the host must still create the LanguageModel instance first
  • this becomes the default model for session execution
  • session.set({ model }) can still override it for one specific session

env

The environment snapshot visible to this agent.

new Agent({
  id: "repo-helper",
  path: "/path/to/project",
  env: {
    OPENAI_API_KEY: process.env.OPENAI_API_KEY ?? "",
  },
});

Key points:

  • the SDK only consumes the explicit environment map you pass in
  • the SDK no longer splits global env and agent env
  • if a host needs layered env merging, it should merge first and then pass the final result through env
  • these values participate in config resolution and runtime context assembly, but are not written back to the system environment automatically

tools

The default tool set at the agent level.

Key points:

  • it belongs to the agent, not the session
  • sessions created by this agent reuse the same tool collection

This is a good fit when multiple sessions should share a stable default tool set.

plugins

This accepts already-instantiated BasePlugin objects.

For example:

import { Agent } from "@downcity/agent";
import { SkillPlugin, WebPlugin } from "@downcity/plugins";

const agent = new Agent({
  id: "repo-helper",
  path: "/path/to/project",
  tools: {},
  plugins: [new SkillPlugin(), new WebPlugin()],
});

The SDK creates an independent plugin registry for the current Agent.

Key points:

  • pass instances such as new SkillPlugin() rather than raw plugin definitions
  • it does not register every built-in plugin by default
  • it does not reuse the global plugin manager
  • duplicate plugin names throw immediately
  • agent.plugins and AgentContext.plugins use this registry
  • if you want the full built-in set, pass plugins: createBuiltinPlugins() from @downcity/plugins