# Source: https://github.com/jina-ai/jina/blob/master/docs/concepts/orchestration/add-executors.md(add-executors)=# Add Executors## Define Executor with `uses`An {class}`~jina.Executor`'s type is defined by the `uses` keyword:````{tab} Deployment```pythonfrom jina import Deploymentdep = Deployment(uses=MyExec)```````````{tab} Flow```pythonfrom jina import Flowf = Flow().add(uses=MyExec)```````Note that some usages are not supported on JCloud due to security reasons and the nature of facilitating local debugging.| Local Dev | JCloud | `uses=...`                              | Description                                                                                               ||-----------|--------|-----------------------------------------------|-----------------------------------------------------------------------------------------------------------|| ✅         | ❌      | `ExecutorClass`                               | Use `ExecutorClass` from the inline context.                                                              || ✅         | ❌      | `'my.py_modules.ExecutorClass'`               | Use `ExecutorClass` from `my.py_modules`.                                                                 || ✅         | ✅      | `'executor-config.yml'`                       | Use an Executor from a YAML file defined by {ref}`Executor YAML interface <executor-yaml-spec>`.          || ✅         | ❌      | `'jinaai://jina-ai/TransformerTorchEncoder/'` | Use an Executor as Python source from Executor Hub.                                                       || ✅         | ✅      | `'jinaai+docker://jina-ai/TransformerTorchEncoder'`  | Use an Executor as a Docker container from Executor Hub.                                                      || ✅         | ❌      | `'docker://sentence-encoder'`                 | Use a pre-built Executor as a Docker container.                                                           |````{admonition} Hint: Load multiple Executors from the same directory:class: hintYou don't need to specify the parent directory for each Executor.Instead, you can configure a common search path for all Executors:```.├── app│   └── ▶ main.py└── executor    ├── config1.yml    ├── config2.yml    └── my_executor.py``````{code-block} pythondep = Deployment(extra_search_paths=['../executor']).add(uses='config1.yml')) # Deploymentf = Flow(extra_search_paths=['../executor']).add(uses='config1.yml').add(uses='config2.yml') # Flow```````(flow-configure-executors)=## Configure ExecutorsYou can set and override {class}`~jina.Executor` configuration when adding them to an Orchestration.This example shows how to start a Flow with an Executor using the Python API:````{tab} Deployment```pythonfrom jina import Deploymentdep = Deployment(    uses='MyExecutor',    py_modules=["executor.py"],    uses_with={"parameter_1": "foo", "parameter_2": "bar"},    uses_metas={        "name": "MyExecutor",        "description": "MyExecutor does a thing to the stuff in your Documents",    },    uses_requests={"/index": "my_index", "/search": "my_search", "/random": "foo"},    workspace="some_custom_path",)with dep:    ...```````````{tab} Flow```pythonfrom jina import Flowf = Flow().add(    uses='MyExecutor',    py_modules=["executor.py"],    uses_with={"parameter_1": "foo", "parameter_2": "bar"},    uses_metas={        "name": "MyExecutor",        "description": "MyExecutor does a thing to the stuff in your Documents",    },    uses_requests={"/index": "my_index", "/search": "my_search", "/random": "foo"},    workspace="some_custom_path",)with f:    ...```````- `py_modules` is a list of strings that defines the Executor's Python dependencies;- `uses_with` is a key-value map that defines the {ref}`arguments of the Executor'<executor-args>` `__init__` method.- `uses_requests` is a key-value map that defines the {ref}`mapping from endpoint to class method<executor-requests>`. This is useful to overwrite the default endpoint-to-method mapping defined in the Executor python implementation.- `uses_metas` is a key-value map that defines some of the Executor's {ref}`internal attributes<executor-metas>`. It contains the following fields:    - `name` is a string that defines the name of the Executor;    - `description` is a string that defines the description of this Executor. It is used in the automatic docs UI;- `workspace` is a string that defines the {ref}`workspace <executor-workspace>`.### Set `with` via `uses_with`To set/override an Executor's `with` configuration, use `uses_with`. The `with` configuration refers to user-definedconstructor kwargs.````{tab} Deployment```pythonfrom jina import Executor, requests, Deploymentclass MyExecutor(Executor):    def __init__(self, param1=1, param2=2, param3=3, *args, **kwargs):        super().__init__(*args, **kwargs)        self.param1 = param1        self.param2 = param2        self.param3 = param3    @requests    def foo(self, docs, **kwargs):        print('param1:', self.param1)        print('param2:', self.param2)        print('param3:', self.param3)dep = Deployment(uses=MyExecutor, uses_with={'param1': 10, 'param3': 30})with dep:    dep.post('/')``````text      executor0@219662[L]:ready and listening        gateway@219662[L]:ready and listening           Deployment@219662[I]:🎉 Deployment is ready to use!	🔗 Protocol: 		GRPC	🏠 Local access:	0.0.0.0:32825	🔒 Private network:	192.168.1.101:32825	🌐 Public address:	197.28.82.165:32825param1: 10param2: 2param3: 30```````````{tab} Flow```pythonfrom jina import Executor, requests, Flowclass MyExecutor(Executor):    def __init__(self, param1=1, param2=2, param3=3, *args, **kwargs):        super().__init__(*args, **kwargs)        self.param1 = param1        self.param2 = param2        self.param3 = param3    @requests    def foo(self, docs, **kwargs):        print('param1:', self.param1)        print('param2:', self.param2)        print('param3:', self.param3)f = Flow().add(uses=MyExecutor, uses_with={'param1': 10, 'param3': 30})with f:    f.post('/')``````text      executor0@219662[L]:ready and listening        gateway@219662[L]:ready and listening           Flow@219662[I]:🎉 Flow is ready to use!	🔗 Protocol: 		GRPC	🏠 Local access:	0.0.0.0:32825	🔒 Private network:	192.168.1.101:32825	🌐 Public address:	197.28.82.165:32825param1: 10param2: 2param3: 30```````### Set `requests` via `uses_requests`You can set/override an Executor's `requests` configuration and bind methods to custom endpoints.In the following code:- We replace the endpoint `/foo` bound to the `foo()` function with both `/non_foo` and `/alias_foo`.- We add a new endpoint `/bar` for binding `bar()`.Note the `all_req()` function is bound to **all** endpoints except those explicitly bound to other functions, i.e. `/non_foo`, `/alias_foo` and `/bar`.````{tab} Deployment```pythonfrom jina import Executor, requests, Deploymentclass MyExecutor(Executor):    @requests    def all_req(self, parameters, **kwargs):        print(f'all req {parameters.get("recipient")}')    @requests(on='/foo')    def foo(self, parameters, **kwargs):        print(f'foo {parameters.get("recipient")}')    def bar(self, parameters, **kwargs):        print(f'bar {parameters.get("recipient")}')dep = Deployment(    uses=MyExecutor,    uses_requests={        '/bar': 'bar',        '/non_foo': 'foo',        '/alias_foo': 'foo',    },)with dep    dep.post('/bar', parameters={'recipient': 'bar()'})    dep.post('/non_foo', parameters={'recipient': 'foo()'})    dep.post('/foo', parameters={'recipient': 'all_req()'})    dep.post('/alias_foo', parameters={'recipient': 'foo()'})``````text      executor0@221058[L]:ready and listening        gateway@221058[L]:ready and listening           Deployment@221058[I]:🎉 Deployment is ready to use!	🔗 Protocol: 		GRPC	🏠 Local access:	0.0.0.0:36507	🔒 Private network:	192.168.1.101:36507	🌐 Public address:	197.28.82.165:36507bar bar()foo foo()all req all_req()foo foo()```````````{tab} Flow```pythonfrom jina import Executor, requests, Flowclass MyExecutor(Executor):    @requests    def all_req(self, parameters, **kwargs):        print(f'all req {parameters.get("recipient")}')    @requests(on='/foo')    def foo(self, parameters, **kwargs):        print(f'foo {parameters.get("recipient")}')    def bar(self, parameters, **kwargs):        print(f'bar {parameters.get("recipient")}')f = Flow().add(    uses=MyExecutor,    uses_requests={        '/bar': 'bar',        '/non_foo': 'foo',        '/alias_foo': 'foo',    },)with f:    f.post('/bar', parameters={'recipient': 'bar()'})    f.post('/non_foo', parameters={'recipient': 'foo()'})    f.post('/foo', parameters={'recipient': 'all_req()'})    f.post('/alias_foo', parameters={'recipient': 'foo()'})``````text      executor0@221058[L]:ready and listening        gateway@221058[L]:ready and listening           Flow@221058[I]:🎉 Flow is ready to use!	🔗 Protocol: 		GRPC	🏠 Local access:	0.0.0.0:36507	🔒 Private network:	192.168.1.101:36507	🌐 Public address:	197.28.82.165:36507bar bar()foo foo()all req all_req()foo foo()```````### Set `metas` via `uses_metas`To set/override an Executor's `metas` configuration, use `uses_metas`:````{tab} Deployment```pythonfrom jina import Executor, requests, Deploymentclass MyExecutor(Executor):    @requests    def foo(self, docs, **kwargs):        print(self.metas.name)dep = Deployment(    uses=MyExecutor,    uses_metas={'name': 'different_name'},)with dep:    dep.post('/')``````text      executor0@219291[L]:ready and listening        gateway@219291[L]:ready and listening           Deployment@219291[I]:🎉 Deployment is ready to use!	🔗 Protocol: 		GRPC	🏠 Local access:	0.0.0.0:58827	🔒 Private network:	192.168.1.101:58827different_name```````````{tab} Flow```pythonfrom jina import Executor, requests, Flowclass MyExecutor(Executor):    @requests    def foo(self, docs, **kwargs):        print(self.metas.name)flow = Flow().add(    uses=MyExecutor,    uses_metas={'name': 'different_name'},)with flow as f:    f.post('/')``````text      executor0@219291[L]:ready and listening        gateway@219291[L]:ready and listening           Flow@219291[I]:🎉 Flow is ready to use!	🔗 Protocol: 		GRPC	🏠 Local access:	0.0.0.0:58827	🔒 Private network:	192.168.1.101:58827different_name```````(external-executors)=## Use external ExecutorsUsually an Orchestration starts and stops its own Executor(s). External Executors are owned by *other* Orchestrations, meaning they can reside on any machine and their lifetime are controlled by others.Using external Executors is useful for sharing expensive Executors (like stateless, GPU-based encoders) between Orchestrations.Both {ref}`served and shared Executors <serve-executor-standalone>` can be used as external Executors.When you add an external Executor, you have to provide a `host` and `port`, and enable the `external` flag:````{tab} Deployment```pythonfrom jina import DeploymentDeployment(host='123.45.67.89', port=12345, external=True)# orDeployment(host='123.45.67.89:12345', external=True)```````````{tab} Flow```pythonfrom jina import FlowFlow().add(host='123.45.67.89', port=12345, external=True)# orFlow().add(host='123.45.67.89:12345', external=True)```````The Orchestration doesn't start or stop this Executor and assumes that it is externally managed and available at `123.45.67.89:12345`.Despite the lifetime control, the external Executor behaves just like a regular one. You can even add the same Executor to multiple Orchestrations.### Enable TLSYou can also use external Executors with `tls`:````{tab} Deployment```pythonfrom jina import DeploymentDeployment(host='123.45.67.89:443', external=True, tls=True)```````````{tab} Flow```pythonfrom jina import FlowFlow().add(host='123.45.67.89:443', external=True, tls=True)```````After that, the external Executor behaves just like an internal one. You can even add the same Executor to multiple Orchestrations.```{hint}Using `tls` to connect to the External Executor is especially needed to use an external Executor deployed with JCloud. See the JCloud {ref}`documentation <jcloud>` for further details```### Pass argumentsExternal Executors may require extra configuration to run. Think about an Executor that requires authentication to run. You can pass the `grpc_metadata` parameter to the Executor. `grpc_metadata` is a dictionary of key-value pairs to be passed along with every gRPC request sent to that Executor.````{tab} Deployment```pythonfrom jina import DeploymentDeployment(    host='123.45.67.89',    port=443,    external=True,    grpc_metadata={'authorization': '<TOKEN>'},)```````````{tab} Flow```pythonfrom jina import FlowFlow().add(    host='123.45.67.89',    port=443,    external=True,    grpc_metadata={'authorization': '<TOKEN>'},)``````````{hint}The `grpc_metadata` parameter here follows the `metadata` concept in gRPC. See [gRPC documentation](https://grpc.io/docs/what-is-grpc/core-concepts/#metadata) for details.```