Configuration

The A2A Java SDK uses a flexible configuration system that works across different frameworks.

Default behavior: Configuration values come from META-INF/a2a-defaults.properties files on the classpath (provided by core modules and extras). These defaults work out of the box without any additional setup.

Customizing configuration:

  • Quarkus/MicroProfile Config users: Add the microprofile-config integration to override defaults via application.properties, environment variables, or system properties
  • Spring/other frameworks: Implement a custom A2AConfigProvider (see Custom Config Providers below)
  • Reference implementations: Already include the MicroProfile Config integration

Configuration Properties

Executor Settings

The SDK uses a dedicated executor for async operations like streaming. Default: 5 core threads, 50 max threads.

# Core thread pool size for the @Internal executor (default: 5)
a2a.executor.core-pool-size=5

# Maximum thread pool size (default: 50)
a2a.executor.max-pool-size=50

# Thread keep-alive time in seconds (default: 60)
a2a.executor.keep-alive-seconds=60

# Queue capacity for pending tasks (default: 100)
# When the queue is full, new threads are created up to max-pool-size
a2a.executor.queue-capacity=100

Blocking Call Timeouts

# Timeout for agent execution in blocking calls (default: 30 seconds)
a2a.blocking.agent.timeout.seconds=30

# Timeout for event consumption in blocking calls (default: 5 seconds)
a2a.blocking.consumption.timeout.seconds=5

# Timeout for TaskStore reconciliation polling in blocking calls (default: 1 second)
a2a.blocking.reconciliation.timeout.seconds=1

Agent Card Caching

# HTTP Cache-Control max-age for Agent Card responses in seconds (default: 3600)
a2a.agent-card.cache.max-age=3600

Request Context

# Load referenced tasks from the TaskStore and enforce authorization checks (default: true)
a2a.request-context.populate-referred-tasks=true

When enabled, task IDs referenced in incoming messages are looked up in the TaskStore and made available to the AgentExecutor via RequestContext.getRelatedTasks(). This is useful for multi-task conversations where the agent needs access to state from related tasks. Enabled by default; set to false to avoid extra TaskStore lookups when not needed.

Tuning Guidelines

  • Streaming Performance: The executor handles streaming subscriptions. Too few threads can cause timeouts under concurrent load.
  • Resource Management: The dedicated executor prevents streaming operations from competing with the ForkJoinPool.
  • Concurrency: In production with high concurrent streaming, increase pool sizes accordingly.
  • Agent Timeouts: LLM-based agents may need longer timeouts (60-120s) compared to simple agents.
  • Reconciliation Timeout: Increase if blocking calls fail with "Could not find a Task/Message" under heavy load or with slow TaskStore implementations.

MicroProfile Config Integration

Add the integration dependency to override configuration via standard MicroProfile Config sources:

<dependency>
    <groupId>org.a2aproject.sdk</groupId>
    <artifactId>a2a-java-sdk-microprofile-config</artifactId>
    <version>${org.a2aproject.sdk.version}</version>
</dependency>

Once added, you can set any A2A property through:

application.properties:

a2a.executor.core-pool-size=10
a2a.executor.max-pool-size=100
a2a.blocking.agent.timeout.seconds=60

Environment variables:

export A2A_EXECUTOR_CORE_POOL_SIZE=10
export A2A_BLOCKING_AGENT_TIMEOUT_SECONDS=60

System properties:

java -Da2a.executor.core-pool-size=10 -jar your-app.jar

Configuration Fallback Chain

MicroProfile Config Sources (application.properties, env vars, -D flags)
  | (not found?)
DefaultValuesConfigProvider
  -> Scans classpath for ALL META-INF/a2a-defaults.properties files
  -> Merges all discovered properties together
  -> Throws exception if duplicate keys found
  | (property exists?)
Return merged default value
  | (not found?)
IllegalArgumentException

All META-INF/a2a-defaults.properties files (from server-common, extras modules, etc.) are loaded and merged together by DefaultValuesConfigProvider at startup. This is not a sequential fallback chain, but a single merged set of defaults.

Framework Compatibility

The MicroProfile Config integration works with any MicroProfile Config implementation:

  • Quarkus -- Built-in MicroProfile Config support
  • Helidon -- Built-in MicroProfile Config support
  • Open Liberty -- Built-in MicroProfile Config support
  • WildFly/JBoss EAP -- Add smallrye-config dependency
  • Other Jakarta EE servers -- Add MicroProfile Config implementation

Custom Config Providers

If you're using a different framework (Spring, Micronaut, etc.), implement your own A2AConfigProvider:

@ApplicationScoped
@Alternative
@Priority(100)  // Higher than MicroProfileConfigProvider's priority of 50
public class MyConfigProvider implements A2AConfigProvider {

    private final Properties customConfig;

    @Inject
    DefaultValuesConfigProvider defaultValues;

    MyConfigProvider() {
        customConfig = loadFromYourFramework();
    }

    @Override
    public String getValue(String name) {
        String value = customConfig.getProperty(name);
        if (value != null) {
            return value;
        }
        return defaultValues.getValue(name);
    }

    @Override
    public Optional<String> getOptionalValue(String name) {
        String value = customConfig.getProperty(name);
        if (value != null) {
            return Optional.of(value);
        }
        return defaultValues.getOptionalValue(name);
    }
}

Note: The reference server implementations (Quarkus-based) automatically include the MicroProfile Config integration, so properties work out of the box in application.properties.