The allocated port is exposed as {@link #httpPort()} and substituted into launch args via the
+ * {@code ${app.httpPort}} placeholder:
+ *
+ *
{
+ private Builder(String name) {
+ super(name);
+ }
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+
+ @Override
+ public SmokeServerApp build() {
+ validate();
+ return new SmokeServerApp(this);
+ }
+ }
+}
diff --git a/dd-smoke-tests/src/main/java/datadog/smoketest/backend/MockAgentBackend.java b/dd-smoke-tests/src/main/java/datadog/smoketest/backend/MockAgentBackend.java
new file mode 100644
index 00000000000..8f029a4cf57
--- /dev/null
+++ b/dd-smoke-tests/src/main/java/datadog/smoketest/backend/MockAgentBackend.java
@@ -0,0 +1,138 @@
+package datadog.smoketest.backend;
+
+import datadog.trace.agent.test.server.http.JavaTestHttpServer;
+import datadog.trace.agent.test.server.http.JavaTestHttpServer.HandlerApi;
+import datadog.trace.test.agent.decoder.DecodedMessage;
+import datadog.trace.test.agent.decoder.DecodedTrace;
+import datadog.trace.test.agent.decoder.Decoder;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * In-process mock-agent {@link TraceBackend} wrapping the testing {@link JavaTestHttpServer}. It
+ * answers the tracer's {@code /info} probe, decodes the trace payloads the tracer submits (v0.4 /
+ * v0.5 / v1.0 msgpack) via the shared {@link Decoder}, and 200s everything else so the app's other
+ * agent calls (telemetry, remote-config, ...) don't error out.
+ *
+ * Backend-specific capture surfaces (remote-config / EVP-proxy / DSM) would hang off this
+ * concrete type rather than the common {@link TraceBackend} facade.
+ */
+public final class MockAgentBackend extends TraceBackend {
+ // Minimal agent-info payload advertising the trace endpoints, mirroring the real agent's /info
+ // (see SimpleAgentMock). The tracer negotiates its trace encoding from this list.
+ private static final String INFO_BODY =
+ "{\"version\":\"7.77.0\",\"endpoints\":[\"/v0.4/traces\",\"/v0.5/traces\",\"/v1.0/traces\"]}";
+ private static final String JSON = "application/json";
+
+ private final List traces = new CopyOnWriteArrayList<>();
+ private final List