diff --git a/IPython/__init__.py b/IPython/__init__.py
index d2c3345..1d7698e 100644
--- a/IPython/__init__.py
+++ b/IPython/__init__.py
@@ -58,13 +58,29 @@ for author, email in release.authors.itervalues():
 __license__  = release.license
 __version__  = release.version
 
-def embed_kernel(module=None, local_ns=None):
-    """Call this to embed an IPython kernel at the current point in your program. """
+def embed_kernel(module=None, local_ns=None, **kwargs):
+    """Embed and start an IPython kernel in a given scope.
+    
+    Parameters
+    ----------
+    module : ModuleType, optional
+        The module to load into IPython globals (default: caller)
+    local_ns : dict, optional
+        The namespace to load into IPython user namespace (default: caller)
+    
+    kwargs : various, optional
+        Further keyword args are relayed to the KernelApp constructor,
+        allowing configuration of the Kernel.  Will only have an effect
+        on the first embed_kernel call for a given process.
+    
+    """
+    
     (caller_module, caller_locals) = extract_module_locals(1)
     if module is None:
         module = caller_module
     if local_ns is None:
         local_ns = caller_locals
+    
     # Only import .zmq when we really need it
     from .zmq.ipkernel import embed_kernel as real_embed_kernel
-    real_embed_kernel(module, local_ns)
+    real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
diff --git a/IPython/zmq/ipkernel.py b/IPython/zmq/ipkernel.py
index 968ca3f..ba0e205 100755
--- a/IPython/zmq/ipkernel.py
+++ b/IPython/zmq/ipkernel.py
@@ -39,6 +39,7 @@ from IPython.core.shellapp import (
 )
 from IPython.utils import io
 from IPython.utils import py3compat
+from IPython.utils.frame import extract_module_locals
 from IPython.utils.jsonutil import json_clean
 from IPython.utils.traitlets import (
     Any, Instance, Float, Dict, CaselessStrEnum
@@ -70,8 +71,17 @@ class Kernel(Configurable):
     iopub_socket = Instance('zmq.Socket')
     stdin_socket = Instance('zmq.Socket')
     log = Instance(logging.Logger)
+    
     user_module = Instance('types.ModuleType')
-    user_ns     = Dict(default_value=None)
+    def _user_module_changed(self, name, old, new):
+        if self.shell is not None:
+            self.shell.user_module = new
+    
+    user_ns = Dict(default_value=None)
+    def _user_ns_changed(self, name, old, new):
+        if self.shell is not None:
+            self.shell.user_ns = new
+            self.shell.init_user_ns()
 
     # Private interface
 
@@ -566,6 +576,7 @@ class IPKernelApp(KernelApp, InteractiveShellApp):
     aliases = Dict(aliases)
     flags = Dict(flags)
     classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
+    
     # configurables
     pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
         config=True,
@@ -589,8 +600,6 @@ class IPKernelApp(KernelApp, InteractiveShellApp):
                                 stdin_socket=self.stdin_socket,
                                 log=self.log,
                                 profile_dir=self.profile_dir,
-                                user_module=self.user_module,
-                                user_ns=self.user_ns,
         )
         self.kernel = kernel
         kernel.record_ports(self.ports)
@@ -645,9 +654,39 @@ def launch_kernel(*args, **kwargs):
     return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
                               *args, **kwargs)
 
-def embed_kernel(module, local_ns):
-    app = IPKernelApp.instance(user_module=module, user_ns=local_ns)
-    app.initialize([])
+
+def embed_kernel(module=None, local_ns=None, **kwargs):
+    """Embed and start an IPython kernel in a given scope.
+    
+    Parameters
+    ----------
+    module : ModuleType, optional
+        The module to load into IPython globals (default: caller)
+    local_ns : dict, optional
+        The namespace to load into IPython user namespace (default: caller)
+    
+    kwargs : various, optional
+        Further keyword args are relayed to the KernelApp constructor,
+        allowing configuration of the Kernel.  Will only have an effect
+        on the first embed_kernel call for a given process.
+    
+    """
+    # get the app if it exists, or set it up if it doesn't
+    if IPKernelApp.initialized():
+        app = IPKernelApp.instance()
+    else:
+        app = IPKernelApp.instance(**kwargs)
+        app.initialize([])
+
+    # load the calling scope if not given
+    (caller_module, caller_locals) = extract_module_locals(1)
+    if module is None:
+        module = caller_module
+    if local_ns is None:
+        local_ns = caller_locals
+    
+    app.kernel.user_module = module
+    app.kernel.user_ns = local_ns
     app.start()
 
 def main():