diff --git a/cookbook/en/deployment/agent_app.md b/cookbook/en/deployment/agent_app.md index d209427b..dc3ed9b6 100644 --- a/cookbook/en/deployment/agent_app.md +++ b/cookbook/en/deployment/agent_app.md @@ -46,6 +46,30 @@ agentApp.run("localhost",10001); ------ +## Configuring Cross-Origin Resource Sharing (CORS) + +**Feature** + +Allow applying custom CORS policies when starting `AgentApp`, so that frontends on different domains or ports can directly call the APIs. + +**Usage Example** + +```java +AgentApp agentApp = new AgentApp(agentHandler); +agentApp.cors(registry -> registry.addMapping("/**") + .allowedOrigins("*") + .allowedMethods("GET", "POST", "PUT", "DELETE") + .allowCredentials(true)); +agentApp.run("localhost", 10001); +``` + +**Notes** + +- The provided lambda is applied directly to Spring's `CorsRegistry`, so you can restrict paths, origins, methods, or customize `allowedHeaders` / `exposedHeaders` as needed. +- If `cors(...)` is not called, `AgentApp` keeps the original default behavior (no CORS enabled). + +------ + ## A2A Streaming Output (SSE) **Features** diff --git a/cookbook/zh/deployment/agent_app.md b/cookbook/zh/deployment/agent_app.md index 36b44554..1ddee884 100644 --- a/cookbook/zh/deployment/agent_app.md +++ b/cookbook/zh/deployment/agent_app.md @@ -46,6 +46,30 @@ agentApp.run("localhost",10001); ------ +## 配置跨域(CORS) + +**功能** + +允许在启动 `AgentApp` 时应用自定义的跨域策略,便于前端在不同域名或端口直接调用接口。 + +**用法示例** + +```java +AgentApp agentApp = new AgentApp(agentHandler); +agentApp.cors(registry -> registry.addMapping("/**") + .allowedOrigins("*") + .allowedMethods("GET", "POST", "PUT", "DELETE") + .allowCredentials(true)); +agentApp.run("localhost", 10001); +``` + +**说明** + +- 传入的 lambda 将直接作用于 Spring 的 `CorsRegistry`,可按需限制路径、来源、方法或自定义 `allowedHeaders` / `exposedHeaders` 等。 +- 若未调用 `cors(...)`,AgentApp 保持默认(不开启跨域)行为。 + +------ + ## A2A 流式输出(SSE) **功能** diff --git a/examples/simple_agent_use_examples/agentscope_use_example/src/main/java/io/agentscope/AgentScopeDeployExample.java b/examples/simple_agent_use_examples/agentscope_use_example/src/main/java/io/agentscope/AgentScopeDeployExample.java index b524ce3b..f4e19630 100755 --- a/examples/simple_agent_use_examples/agentscope_use_example/src/main/java/io/agentscope/AgentScopeDeployExample.java +++ b/examples/simple_agent_use_examples/agentscope_use_example/src/main/java/io/agentscope/AgentScopeDeployExample.java @@ -49,6 +49,10 @@ private static void runAgent() { agentHandler.setSandboxService(buidSandboxService()); AgentApp agentApp = new AgentApp(agentHandler); + agentApp.cors(registry -> registry.addMapping("/**") + .allowedOriginPatterns("*") + .allowedMethods("GET", "POST", "PUT", "DELETE") + .allowCredentials(true)); agentApp.run(10001); } diff --git a/web/src/main/java/io/agentscope/runtime/LocalDeployManager.java b/web/src/main/java/io/agentscope/runtime/LocalDeployManager.java index 574b6bce..10d45598 100644 --- a/web/src/main/java/io/agentscope/runtime/LocalDeployManager.java +++ b/web/src/main/java/io/agentscope/runtime/LocalDeployManager.java @@ -28,11 +28,14 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; +import java.util.function.Consumer; public class LocalDeployManager implements DeployManager { Logger logger = Logger.getLogger(LocalDeployManager.class.getName()); @@ -44,6 +47,7 @@ public class LocalDeployManager implements DeployManager { private final int port; private final List protocols; private final List protocolConfigs; + private final Consumer corsConfigurer; private LocalDeployManager(LocalDeployerManagerBuilder builder) { this.endpointName = builder.endpointName; @@ -51,6 +55,7 @@ private LocalDeployManager(LocalDeployerManagerBuilder builder) { this.port = builder.port; this.protocols = builder.protocols; this.protocolConfigs = builder.protocolConfigs; + this.corsConfigurer = builder.corsConfigurer; } @Override @@ -93,6 +98,14 @@ public synchronized void deploy(Runner runner) { ctx.registerBean(protocolConfig.name(), ProtocolConfig.class, () -> protocolConfig); } } + if (corsConfigurer != null) { + ctx.registerBean(WebMvcConfigurer.class, () -> new WebMvcConfigurer() { + @Override + public void addCorsMappings(CorsRegistry registry) { + corsConfigurer.accept(registry); + } + }); + } }) .run(); @@ -134,6 +147,7 @@ public static class LocalDeployerManagerBuilder { private int port = 8080; private List protocols = List.of(Protocol.A2A, Protocol.ResponseAPI); private List protocolConfigs = List.of(); + private Consumer corsConfigurer; public LocalDeployerManagerBuilder endpointName(String endpointName) { this.endpointName = endpointName; @@ -160,6 +174,11 @@ public LocalDeployerManagerBuilder protocolConfigs(List protocol return this; } + public LocalDeployerManagerBuilder corsConfigurer(Consumer corsConfigurer) { + this.corsConfigurer = corsConfigurer; + return this; + } + public LocalDeployManager build() { return new LocalDeployManager(this); } diff --git a/web/src/main/java/io/agentscope/runtime/app/AgentApp.java b/web/src/main/java/io/agentscope/runtime/app/AgentApp.java index e97282d6..21ee96bd 100644 --- a/web/src/main/java/io/agentscope/runtime/app/AgentApp.java +++ b/web/src/main/java/io/agentscope/runtime/app/AgentApp.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.function.Consumer; import java.util.function.Function; import io.agentscope.runtime.LocalDeployManager; @@ -29,6 +30,7 @@ import io.agentscope.runtime.protocol.ProtocolConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.web.servlet.config.annotation.CorsRegistry; /** * AgentApp class represents an application that runs as an agent. @@ -66,6 +68,7 @@ public class AgentApp { private int port = 8090; private boolean stream = true; private String responseType = "sse"; + private Consumer corsConfigurer; private List customEndpoints = new ArrayList<>(); private List protocolConfigs; @@ -151,6 +154,25 @@ public AgentApp deployManager(DeployManager deployManager) { this.deployManager = deployManager; return this; } + + /** + * Configure Cross-Origin Resource Sharing (CORS). + * + *

Usage example:

+ *
{@code
+     * app.cors(registry -> registry.addMapping("/**")
+     *         .allowedOrigins("https://example.com")
+     *         .allowedMethods("GET", "POST")
+     *         .allowCredentials(true));
+     * }
+ * + * @param corsConfigurer consumer to customize {@link CorsRegistry} + * @return this AgentApp instance for method chaining + */ + public AgentApp cors(Consumer corsConfigurer) { + this.corsConfigurer = corsConfigurer; + return this; + } /** * Build the Runner instance by proxying the AgentAdapter. @@ -259,6 +281,7 @@ public void run(String host, int port) { .port(port) .endpointName(endpointPath) .protocolConfigs(protocolConfigs) + .corsConfigurer(corsConfigurer) .build(); }